面向对象
面向对象三大特性
- 封装(Encapsulation)
- 继承(Inheritance)
- 接口继承
- 实现继承
- 多态(Polymorphism)
- 编译时多态
- 运行时多态
C++面向对象编程提供了强大的抽象和代码组织能力:
- 封装保护数据和实现细节
- 继承实现代码复用和层次结构
- 多态提供灵活的接口和实现分离
1. 封装
- 封装是将数据和操作数据的方法绑定在一起
- 类的大小与成员变量和内存对齐有关
- 普通成员函数的调用过程:
- 编译时绑定调用地址
- 隐式this指针:编译器传递this指针作为第一个参数
- 函数代码共享:所有同类对象共享同一份代码
- 程序代码都存储在虚拟内存的.text段
- 访问修饰符:
public:任何地方都可以访问protected:本类和派生类可以访问private:只有本类可以访问
2. 继承
继承允许一个类(派生类)继承另一个类(基类)的属性和方法。
继承的类型:
- 接口继承:使用基类的属性和方法,子类提供实现
- 实现继承:使用基类的属性和方法
继承修饰符:
- 公有继承
public:派生类是基类的一种特化 - 保护继承
protected:较少使用 - 私有继承
private:实现继承,而非接口继承
2.1 override 和 final 关键字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Base {
public:
virtual void func() {}
};
class Derived : public Base {
public:
void func() override {} // 明确表示重写
};
class Final final : public Derived { // 不能被继承
public:
void func() final override {} // 不能被进一步重写
};
2.2 多重继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A {
public:
virtual void funcA() {}
};
class B {
public:
virtual void funcB() {}
};
class C : public A, public B {
public:
void funcA() override {}
void funcB() override {}
};
2.3 菱形继承与虚继承
3. 多态
多态允许不同类的对象对同一消息做出不同的响应。
多态的类型:
- 编译时多态:overload 函数重载、运算符重载、模板
- 运行时多态:override 重写 虚函数
3.1 编译时多态
编译时多态:overload 函数重载、运算符重载、模板
函数重载
函数重载的核心特征:
- 函数名相同:所有重载函数必须使用相同的函数名
- 参数列表不同:参数的类型、数量或顺序必须不同
- 编译时解析:编译器根据调用时的参数自动选择匹配的函数版本
- 返回类型可以不同:但不能仅凭返回类型区分重载函数
- 作用域相同:重载函数必须在同一作用域内
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 函数重载 - 编译时决定调用哪个版本
void print(int value) {
std::cout << "Integer: " << value << std::endl;
}
void print(double value) {
std::cout << "Double: " << value << std::endl;
}
void print(const std::string& value) {
std::cout << "String: " << value << std::endl;
}
// 使用时编译器根据参数类型决定调用哪个函数
print(42); // 调用 print(int)
print(3.14); // 调用 print(double)
print("Hello"); // 调用 print(const std::string&)
运算符重载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Complex {
private:
double real, imag;
public:
Complex operator+(const Complex& other) const {
return Complex(real + other.real, imag + other.imag);
}
Complex& operator=(const Complex& other) {
if (this != &other) {
real = other.real;
imag = other.imag;
}
return *this;
}
};
友元运算符重载
1
2
3
4
5
6
7
8
class Complex {
friend std::ostream& operator<<(std::ostream& os, const Complex& c);
};
std::ostream& operator<<(std::ostream& os, const Complex& c) {
os << c.real << " + " << c.imag << "i";
return os;
}
3.2 运行时多态
运行时多态:override 重写 虚函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Animal { // 基类
protected:
std::string name;
public:
Animal(const std::string& n) : name(n) {}
virtual void makeSound() = 0; // 纯虚函数
virtual ~Animal() = default;
};
class Dog : public Animal { // 派生类
public:
Dog(const std::string& n) : Animal(n) {}
void makeSound() override {
std::cout << name << " says Woof!" << std::endl;
}
};
1
2
3
4
5
6
7
8
9
void playWithAnimal(Animal* animal) {
animal->makeSound(); // 运行时决定调用哪个版本
}
Dog dog("Buddy");
Cat cat("Whiskers");
playWithAnimal(&dog); // 输出: Buddy says Woof!
playWithAnimal(&cat); // 输出: Whiskers says Meow!