如何速通C++面向对象:从语法基础到多态实战

发布时间:2026/6/11 11:27:24
如何速通C++面向对象:从语法基础到多态实战
1. 面向对象编程基础从class开始很多刚接触C的同学一听到面向对象就头疼其实它就像搭积木一样简单。想象你要造一辆车传统做法是从轮子开始一个个零件组装面向过程而面向对象则是先设计好车这个模板然后批量生产。我们先从最基础的class语法开始#include iostream using namespace std; class Student { public: // 构造函数 Student(string name, int age) { this-name name; this-age age; } // 成员函数 void introduce() { cout 我叫 name 今年 age 岁 endl; } private: // 数据成员 string name; int age; }; int main() { Student xiaoming(小明, 18); xiaoming.introduce(); // 输出我叫小明今年18岁 }这里有几个关键点需要注意public和private就像房子的客厅和卧室客厅(public)谁都能进卧室(private)只有主人能进构造函数就像房子的建造图纸决定了如何创建对象实例成员函数是对象能做的事情比如这里的introduce()就是自我介绍我刚开始学的时候经常搞混.和-操作符其实很简单对象用点号obj.method()指针用箭头ptr-method()2. 三大特性之封装把复杂藏起来封装就像智能手机我们只需要会按屏幕不需要知道里面的电路怎么工作。在C中这通过访问控制实现class BankAccount { public: void deposit(int amount) { if (amount 0) balance amount; } int getBalance() { return balance; } private: int balance 0; // 余额对外不可见 }; int main() { BankAccount account; account.deposit(1000); // account.balance 10000; // 错误不能直接访问private成员 cout account.getBalance(); // 正确方式 }封装的好处我深有体会。去年做项目时我把一个类的数据成员都设成public结果队友不小心直接修改了内部状态导致程序崩溃。后来改成private加getter/setter问题就再没出现过。3. 继承代码复用的利器继承就像基因遗传子类会自动获得父类的特性。看这个例子class Animal { public: Animal(string name) : name(name) {} void eat() { cout name 在吃东西 endl; } protected: string name; }; class Cat : public Animal { public: Cat(string name) : Animal(name) {} void meow() { cout name 说喵喵~ endl; } }; int main() { Cat myCat(小花); myCat.eat(); // 继承自Animal myCat.meow(); // 自己的方法 }继承方式有三种public继承父类的public在子类还是publicprotected继承父类的public在子类变成protectedprivate继承父类的public在子类变成private实际项目中public继承最常用约占90%的情况。我在开发游戏时用继承实现了敌人类体系基础敌人→飞行敌人→Boss敌人代码复用率提高了70%。4. 多态面向对象的精髓多态让同一个接口可以有不同的实现方式就像手机的充电接口既能充手机也能充耳机。C通过虚函数实现class Shape { public: virtual void draw() 0; // 纯虚函数 }; class Circle : public Shape { public: void draw() override { cout 画一个圆形 endl; } }; class Square : public Shape { public: void draw() override { cout 画一个方形 endl; } }; void drawShape(Shape* shape) { shape-draw(); // 根据实际对象类型调用对应方法 } int main() { Circle c; Square s; drawShape(c); // 输出画一个圆形 drawShape(s); // 输出画一个方形 }多态在实际开发中非常有用。比如我做UI框架时所有控件继承自基类Widget都有render()方法但按钮、文本框的渲染方式完全不同。通过多态系统可以统一调用render()而不需要关心具体类型。5. 模板类型无关的通用编程模板就像模具可以做出各种形状的饼干。C模板分为函数模板和类模板// 函数模板 template typename T T max(T a, T b) { return a b ? a : b; } // 类模板 template typename T class Stack { private: vectorT elements; public: void push(T const elem) { elements.push_back(elem); } T pop() { T elem elements.back(); elements.pop_back(); return elem; } }; int main() { cout max(1, 2) endl; // 输出2 cout max(1.5, 2.3) endl; // 输出2.3 Stackint intStack; intStack.push(7); cout intStack.pop() endl; // 输出7 }模板元编程是C的强大特性但初学者容易过度使用。我的经验是当发现自己在复制粘贴代码只改类型时就该考虑用模板了。6. 实战技巧与常见坑点虚析构函数基类析构函数必须声明为virtual否则通过基类指针删除派生类对象时派生类的析构函数不会被调用导致内存泄漏。class Base { public: virtual ~Base() {} // 虚析构函数 }; class Derived : public Base { public: ~Derived() { cout Derived析构 endl; } }; int main() { Base* ptr new Derived(); delete ptr; // 会调用Derived的析构函数 }override关键字C11引入的override可以明确表示要重写虚函数避免拼写错误导致的意外隐藏class Base { public: virtual void foo(int) {} }; class Derived : public Base { public: void foo(int) override {} // 正确 // void foo(float) override {} // 编译错误不是重写 };菱形继承问题多继承时可能出现同一个基类被多次继承使用虚继承解决class A {}; class B : virtual public A {}; class C : virtual public A {}; class D : public B, public C {}; // A只被继承一次记得第一次用多继承时我遇到了著名的菱形继承问题调试了整整一天。后来导师告诉我用虚继承问题秒解。这也让我明白C特性强大但要知其所以然。