跳转到内容

C++ 继承

来自代码酷

C++继承[编辑 | 编辑源代码]

继承是C++面向对象编程中的核心概念之一,它允许一个类(称为派生类子类)基于另一个类(称为基类父类)来构建,从而复用代码并建立类之间的层次关系。继承体现了"is-a"关系,是代码重用和多态性的基础。

基本语法[编辑 | 编辑源代码]

C++中继承的基本语法如下:

class BaseClass {
    // 基类成员
};

class DerivedClass : access-specifier BaseClass {
    // 派生类成员
};

其中access-specifier可以是publicprotectedprivate,决定了基类成员在派生类中的访问权限。

继承类型[编辑 | 编辑源代码]

C++支持三种继承方式:

1. 公有继承(public)[编辑 | 编辑源代码]

最常用的继承方式,保持基类成员的原有访问权限:

  • 基类的public成员 → 派生类的public成员
  • 基类的protected成员 → 派生类的protected成员
  • 基类的private成员 → 不可访问
class Animal {
public:
    void breathe() { cout << "Breathing..." << endl; }
protected:
    int age;
};

class Dog : public Animal {
public:
    void bark() { 
        breathe();  // 可以访问基类public方法
        age = 2;    // 可以访问基类protected成员
    }
};

2. 保护继承(protected)[编辑 | 编辑源代码]

  • 基类的public和protected成员 → 派生类的protected成员
  • 基类的private成员 → 不可访问

3. 私有继承(private)[编辑 | 编辑源代码]

  • 基类的public和protected成员 → 派生类的private成员
  • 基类的private成员 → 不可访问

构造函数和析构函数顺序[编辑 | 编辑源代码]

当创建派生类对象时: 1. 先调用基类构造函数 2. 然后调用派生类构造函数 析构时顺序相反。

sequenceDiagram participant D as 派生类对象 participant B as 基类 D->>B: 构造基类部分 B-->>D: 基类构造完成 D->>D: 构造派生类部分 D-->>D: 派生类构造完成 Note right of D: 对象使用中... D->>D: 析构派生类部分 D->>B: 析构基类部分

示例:

class Base {
public:
    Base() { cout << "Base constructor" << endl; }
    ~Base() { cout << "Base destructor" << endl; }
};

class Derived : public Base {
public:
    Derived() { cout << "Derived constructor" << endl; }
    ~Derived() { cout << "Derived destructor" << endl; }
};

int main() {
    Derived d;
    return 0;
}

输出:

Base constructor
Derived constructor
Derived destructor
Base destructor

函数重写与多态[编辑 | 编辑源代码]

派生类可以重写(override)基类的虚函数,实现运行时多态:

class Shape {
public:
    virtual void draw() { cout << "Drawing a shape" << endl; }
    virtual ~Shape() {} // 虚析构函数
};

class Circle : public Shape {
public:
    void draw() override { cout << "Drawing a circle" << endl; }
};

int main() {
    Shape* shape = new Circle();
    shape->draw(); // 输出"Drawing a circle"
    delete shape;
    return 0;
}

多重继承[编辑 | 编辑源代码]

C++支持一个类继承多个基类(但需谨慎使用,可能引发"菱形问题"):

class A {
public:
    void funcA() { cout << "Function A" << endl; }
};

class B {
public:
    void funcB() { cout << "Function B" << endl; }
};

class C : public A, public B {
public:
    void funcC() { 
        funcA(); 
        funcB();
    }
};

虚继承[编辑 | 编辑源代码]

解决多重继承中的菱形问题:

classDiagram class A class B : virtual A class C : virtual A class D : B, C

class A {
public:
    int data;
};

class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};

int main() {
    D d;
    d.data = 10; // 没有二义性
    return 0;
}

实际应用案例[编辑 | 编辑源代码]

GUI框架中的继承 在图形用户界面开发中,继承被广泛使用:

class Widget {
protected:
    int x, y;
public:
    virtual void draw() = 0;
    virtual void handleEvent(Event e) = 0;
};

class Button : public Widget {
    string label;
public:
    void draw() override { /* 绘制按钮 */ }
    void handleEvent(Event e) override {
        if (e.type == Event::Click) {
            // 处理点击事件
        }
    }
};

class CheckBox : public Widget {
    bool checked;
public:
    void draw() override { /* 绘制复选框 */ }
    void handleEvent(Event e) override {
        if (e.type == Event::Click) {
            checked = !checked;
        }
    }
};

继承与组合[编辑 | 编辑源代码]

虽然继承强大,但有时组合(has-a关系)比继承(is-a关系)更合适:

  • 继承:当派生类确实是基类的特殊类型时使用
  • 组合:当一个类需要另一个类的功能但不是其特殊类型时使用

最佳实践[编辑 | 编辑源代码]

1. 优先使用公有继承 2. 谨慎使用多重继承 3. 基类析构函数应声明为virtual 4. 考虑使用final禁止进一步派生 5. 遵循LSP(里氏替换原则):派生类应能完全替代基类

进阶主题[编辑 | 编辑源代码]

  • 协变返回类型
  • 使用using改变基类成员访问权限
  • CRTP(奇异递归模板模式)
  • 接口继承与实现继承

通过掌握继承,您可以构建更灵活、可维护的面向对象系统。记住,继承是手段而非目的,合理设计类层次结构比滥用继承更重要。