C++初识—面向对象
一 面向对象基础概念
四大支柱
概念 描述 C++实现 封装 将数据和行为绑定,隐藏实现细节 class
+ 访问修饰符继承 创建新类基于现有类 class Derived : public Base
多态 同一接口不同实现 虚函数 + 继承 抽象 简化复杂系统,关注接口 纯虚函数、抽象类
类与对象关系
二 类与对象
class MyClass {
private: // 私有成员(默认)int privateVar;protected: // 保护成员int protectedVar;public: // 公有成员// 构造函数MyClass(int a, int b) : privateVar(a), protectedVar(b) {}// 成员函数void display() {cout << privateVar << ", " << protectedVar << endl;}
};int main() {MyClass obj(10, 20);obj.display(); // 输出: 10, 20// obj.privateVar = 5; // 错误:私有成员不可访问
}
对象内存布局
+-----------------+
| privateVar (int)|
+-----------------+
| protectedVar (int)
+-----------------+
| vtable指针 | // 当有虚函数时
+-----------------+
三 构造函数与析构函数
构造函数类型
类型 | 描述 | 示例 |
---|---|---|
默认构造函数 | 无参数 | MyClass() {} |
参数化构造函数 | 带参数 | MyClass(int a) {} |
拷贝构造函数 | 复制对象 | MyClass(const MyClass& other) |
移动构造函数 | 转移资源 | MyClass(MyClass&& other) |
构造函数类型与特性
类型 | 语法 | 调用时机 | 特殊说明 |
---|---|---|---|
默认构造 | ClassName() | 对象默认创建 | 不提供时编译器自动生成 |
参数化构造 | ClassName(params) | 显式带参创建 | 可重载多个版本 |
拷贝构造 | ClassName(const ClassName&) | 对象复制时 | 浅拷贝问题需注意 |
移动构造 | ClassName(ClassName&&) | 临时对象转移 | C++11新增 |
构造函数底层细节
class Complex {
private:double real;double imag;public:// 参数化构造函数Complex(double r, double i) : real(r), imag(i) {// 初始化列表完成后执行此处}// 拷贝构造函数Complex(const Complex& other) : real(other.real), imag(other.imag) {std::cout << "拷贝构造调用\n";}// 移动构造函数Complex(Complex&& other) noexcept : real(std::move(other.real)), imag(std::move(other.imag)) {std::cout << "移动构造调用\n";}
};
内存布局变化:
对象创建前:
[未初始化内存]对象创建后:
+----------------+
| real (8字节) |
+----------------+
| imag (8字节) |
+----------------+
初始化列表的重要性
在构造函数体执行前完成初始化
对const成员和引用成员必须使用
初始化顺序由成员声明顺序决定
class CriticalInit {
private:const int id;int& ref;std::string name;public:// 必须使用初始化列表CriticalInit(int i, int& r, const std::string& n): id(i), ref(r), name(n) {// 构造函数体}
};
特殊成员函数调用时机
构造函数调用机制
析构函数
class ResourceHolder {
private:int* data;public:ResourceHolder(size_t size) {data = new int[size];}// 析构函数~ResourceHolder() {delete[] data;cout << "资源已释放" << endl;}
};
四 封装与访问控制
访问修饰符
修饰符 | 类内 | 派生类 | 外部 |
---|---|---|---|
private | ✔️ | ✖️ | ✖️ |
protected | ✔️ | ✔️ | ✖️ |
public | ✔️ | ✔️ | ✔️ |
封装示例
class BankAccount {
private:double balance;string owner;public:BankAccount(string name, double initial): owner(name), balance(initial) {}void deposit(double amount) {if (amount > 0) balance += amount;}bool withdraw(double amount) {if (amount > 0 && balance >= amount) {balance -= amount;return true;}return false;}double getBalance() const {return balance;}
};
五 继承
继承类型
继承方式 | 基类public | 基类protected | 基类private |
---|---|---|---|
public | public | protected | 不可访问 |
protected | protected | protected | 不可访问 |
private | private | private | 不可访问 |
继承示例
class Shape {
protected:int width, height;public:Shape(int w, int h) : width(w), height(h) {}virtual int area() const = 0; // 纯虚函数
};class Rectangle : public Shape {
public:Rectangle(int w, int h) : Shape(w, h) {}int area() const override {return width * height;}
};class Triangle : public Shape {
public:Triangle(int w, int h) : Shape(w, h) {}int area() const override {return (width * height) / 2;}
};
构造/析构顺序
六 多态
虚函数机制
class Animal {
public:virtual void speak() const {cout << "动物叫声" << endl;}virtual ~Animal() = default; // 虚析构函数
};class Dog : public Animal {
public:void speak() const override {cout << "汪汪!" << endl;}
};class Cat : public Animal {
public:void speak() const override {cout << "喵喵!" << endl;}
};void animalSound(Animal& animal) {animal.speak(); // 多态调用
}int main() {Dog dog;Cat cat;animalSound(dog); // 输出: 汪汪!animalSound(cat); // 输出: 喵喵!
}
vtable(虚函数表)原理
Animal对象:
+----------------+
| vtable指针 | --> +----------------+
+----------------+ | Animal::speak |
| ... | +----------------+Dog对象:
+----------------+
| vtable指针 | --> +----------------+
+----------------+ | Dog::speak |
| ... | +----------------+
override与final
class Animal {
public:virtual void speak() const {cout << "动物叫声" << endl;}virtual ~Animal() = default; // 虚析构函数
};class Dog : public Animal {
public:void speak() const override {cout << "汪汪!" << endl;}
};class Cat : public Animal {
public:void speak() const override {cout << "喵喵!" << endl;}
};void animalSound(Animal& animal) {animal.speak(); // 多态调用
}int main() {Dog dog;Cat cat;animalSound(dog); // 输出: 汪汪!animalSound(cat); // 输出: 喵喵!
}
七 抽象与接口
纯虚函数与抽象类
// 抽象类(接口)
class Drawable {
public:virtual void draw() const = 0; // 纯虚函数virtual ~Drawable() = default;
};// 具体实现
class Circle : public Drawable {
public:void draw() const override {cout << "绘制圆形" << endl;}
};class Square : public Drawable {
public:void draw() const override {cout << "绘制正方形" << endl;}
};void render(const Drawable& obj) {obj.draw(); // 多态调用
}
接口与实现分离
八 友元与静态成员
友元函数/类
class Container {
private:int secret;// 友元函数friend void peek(const Container& c);// 友元类friend class Spy;
};void peek(const Container& c) {cout << "秘密值: " << c.secret << endl;
}class Spy {
public:void reveal(const Container& c) {cout << "间谍获取: " << c.secret << endl;}
};
静态成员
class Counter {
private:static int count; // 静态成员变量public:Counter() {count++;}~Counter() {count--;}static int getCount() { // 静态成员函数return count;}
};int Counter::count = 0; // 静态成员初始化int main() {Counter c1, c2;cout << Counter::getCount(); // 输出: 2{Counter c3;cout << Counter::getCount(); // 输出: 3}cout << Counter::getCount(); // 输出: 2
}
九 运算符重载
常用运算符重载
class Vector {
private:double x, y;public:Vector(double x, double y) : x(x), y(y) {}// 加法运算符重载Vector operator+(const Vector& other) const {return Vector(x + other.x, y + other.y);}// 输出运算符重载 (友元)friend ostream& operator<<(ostream& os, const Vector& v) {return os << "(" << v.x << ", " << v.y << ")";}// 下标运算符重载double operator[](int index) const {if (index == 0) return x;if (index == 1) return y;throw out_of_range("索引超出范围");}
};int main() {Vector v1(1, 2), v2(3, 4);Vector v3 = v1 + v2;cout << v3; // 输出: (4, 6)cout << v3[0]; // 输出: 4
}
可重载运算符表
运算符类型 示例 算术 +
,-
,*
,/
关系 ==
,!=
,<
,>
赋值 =
,+=
,-=
下标 []
函数调用 ()
类型转换 operator int()
十 对象关系与设计原则
对象关系类型
关系 描述 UML表示 继承 "是一个" 实线+空心箭头 组合 "包含一个" 实线+实心菱形 聚合 "有一个" 实线+空心菱形 关联 "使用一个" 实线箭头 依赖 "临时使用" 虚线箭头 SOLID原则
原则 描述 示例 SRP 单一职责 一个类只做一件事 OCP 开闭原则 对扩展开放,修改关闭 LSP 里氏替换 派生类可替换基类 ISP 接口隔离 多个专用接口优于一个通用接口 DIP 依赖倒置 依赖抽象而非具体实现
十一 高级主题
多重继承
class Printer {
public:virtual void print() = 0;
};class Scanner {
public:virtual void scan() = 0;
};class MultiFunctionDevice : public Printer, public Scanner {
public:void print() override {cout << "打印中..." << endl;}void scan() override {cout << "扫描中..." << endl;}
};
虚继承(解决菱形继承)
无图无真相
class A {
public:int value;
};class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};int main() {D d;d.value = 10; // 无歧义
}
运行时类型识别(RTTI)
Base* ptr = new Derived();// dynamic_cast
if (Derived* d = dynamic_cast<Derived*>(ptr)) {d->derivedMethod();
}// typeid
if (typeid(*ptr) == typeid(Derived)) {cout << "对象是Derived类型" << endl;
}
十二 C++对象模型深入
内存布局示例
class Base {
public:virtual void vfunc1() {}virtual void vfunc2() {}int data1;
};class Derived : public Base {
public:virtual void vfunc1() override {}virtual void vfunc3() {}int data2;
};
内存布局
Derived对象:
+----------------+
| vtable指针 | --> +----------------+
+----------------+ | Derived::vfunc1 |
| Base::data1 | | Base::vfunc2 |
+----------------+ | Derived::vfunc3|
| Derived::data2 | +----------------+
+----------------+
对象模型关键点
成员变量:按声明顺序排列
虚函数:通过vtable实现
继承:
单继承:派生类包含基类子对象
多继承:包含多个基类子对象
虚继承:共享基类子对象
内存对齐:根据平台优化访问速度
性能考虑
虚函数调用比普通函数慢(多一次间接寻址)
小对象频繁创建/销毁时考虑对象池
避免深度继承层次(通常不超过3层)
优先使用组合而非继承
总结
C++面向对象编程的核心要点:
封装是基础:通过访问控制实现信息隐藏
继承需谨慎:优先使用组合而非继承
多态是核心:虚函数实现运行时多态
资源管理:RAII原则(构造获取,析构释放)
对象关系:理解组合/聚合/关联/依赖区别
设计原则:遵循SOLID原则创建可维护系统
对象模型:理解内存布局优化性能
掌握这些概念需要大量实践,特别是:
多态的实现机制
拷贝控制(三/五法则)
虚函数表原理
对象内存布局
设计模式应用