c++面向对象

本文讲解c++面向对象相关内容;封装,继承,多态(编译时多态与运行时多态)等。

Posted by CongYu on August 1, 2020

面向对象

面向对象三大特性

  • 封装(Encapsulation)
  • 继承(Inheritance)
    • 接口继承
    • 实现继承
  • 多态(Polymorphism)
    • 编译时多态
    • 运行时多态

C++面向对象编程提供了强大的抽象和代码组织能力:

  1. 封装保护数据和实现细节
  2. 继承实现代码复用和层次结构
  3. 多态提供灵活的接口和实现分离

1. 封装

  • 封装是将数据和操作数据的方法绑定在一起
  • 类的大小与成员变量和内存对齐有关
  • 普通成员函数的调用过程:
    • 编译时绑定调用地址
    • 隐式this指针:编译器传递this指针作为第一个参数
    • 函数代码共享:所有同类对象共享同一份代码
  • 程序代码都存储在虚拟内存的.text段
  • 访问修饰符:
    • public:任何地方都可以访问
    • protected:本类和派生类可以访问
    • private:只有本类可以访问

2. 继承

继承允许一个类(派生类)继承另一个类(基类)的属性和方法。

继承的类型:

  • 接口继承:使用基类的属性和方法,子类提供实现
  • 实现继承:使用基类的属性和方法

继承修饰符:

  • 公有继承public:派生类是基类的一种特化
  • 保护继承protected:较少使用
  • 私有继承private:实现继承,而非接口继承

2.1 override 和 final 关键字

2020-10-01-override

2020-10-02-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 菱形继承与虚继承

2022-02-18-菱形继承与虚继承

3. 多态

多态允许不同类的对象对同一消息做出不同的响应。

多态的类型:

  1. 编译时多态:overload 函数重载、运算符重载、模板
  2. 运行时多态:override 重写 虚函数

3.1 编译时多态

编译时多态:overload 函数重载、运算符重载、模板

函数重载

函数重载的核心特征:

  1. 函数名相同:所有重载函数必须使用相同的函数名
  2. 参数列表不同:参数的类型、数量或顺序必须不同
  3. 编译时解析:编译器根据调用时的参数自动选择匹配的函数版本
  4. 返回类型可以不同:但不能仅凭返回类型区分重载函数
  5. 作用域相同:重载函数必须在同一作用域内
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!

虚函数原理

2022-02-01-虚函数原理