跳转到内容

C++ 基类与派生类

来自代码酷

C++基类与派生类[编辑 | 编辑源代码]

基类(Base Class)派生类(Derived Class)是C++面向对象编程中实现继承机制的核心概念。继承允许我们基于一个已有的类(基类)定义一个新类(派生类),派生类继承了基类的特性,同时可以添加自己的新特性或修改继承的特性。

基本概念[编辑 | 编辑源代码]

在C++中,继承的语法如下:

class BaseClass {
    // 基类成员
};

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

其中:

  • BaseClass是已有的类(基类)
  • DerivedClass是新创建的类(派生类)
  • access-specifier是访问说明符(public、protected或private)

访问控制与继承[编辑 | 编辑源代码]

C++提供了三种继承方式:

继承类型及其影响
继承类型 基类public成员 基类protected成员 基类private成员
public继承 派生类public成员 派生类protected成员 不可访问
protected继承 派生类protected成员 派生类protected成员 不可访问
private继承 派生类private成员 派生类private成员 不可访问

代码示例[编辑 | 编辑源代码]

下面是一个简单的继承示例:

#include <iostream>
using namespace std;

// 基类
class Shape {
protected:
    int width, height;
public:
    void setDimensions(int w, int h) {
        width = w;
        height = h;
    }
};

// 派生类
class Rectangle : public Shape {
public:
    int area() {
        return width * height;
    }
};

int main() {
    Rectangle rect;
    rect.setDimensions(5, 3);
    cout << "矩形面积: " << rect.area() << endl;
    return 0;
}

输出:

矩形面积: 15

继承中的构造函数与析构函数[编辑 | 编辑源代码]

派生类不继承基类的构造函数和析构函数,但可以在派生类构造函数中调用基类构造函数:

class Base {
public:
    Base() { cout << "基类构造函数" << endl; }
    ~Base() { cout << "基类析构函数" << endl; }
};

class Derived : public Base {
public:
    Derived() { cout << "派生类构造函数" << endl; }
    ~Derived() { cout << "派生类析构函数" << endl; }
};

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

输出:

基类构造函数
派生类构造函数
派生类析构函数
基类析构函数

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

C++支持多级继承,即一个派生类可以作为另一个派生类的基类:

classDiagram class A class B : A class C : B

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

考虑一个图形编辑软件中的形状系统:

class Shape {
protected:
    string color;
public:
    virtual void draw() = 0;  // 纯虚函数
    void setColor(string c) { color = c; }
};

class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    void draw() override {
        cout << "绘制圆形,半径: " << radius 
             << ",颜色: " << color << endl;
    }
};

class Rectangle : public Shape {
    double width, height;
public:
    Rectangle(double w, double h) : width(w), height(h) {}
    void draw() override {
        cout << "绘制矩形,宽: " << width 
             << ",高: " << height 
             << ",颜色: " << color << endl;
    }
};

int main() {
    Circle c(5.0);
    c.setColor("红色");
    c.draw();
    
    Rectangle r(4.0, 6.0);
    r.setColor("蓝色");
    r.draw();
    
    return 0;
}

输出:

绘制圆形,半径: 5,颜色: 红色
绘制矩形,宽: 4,高: 6,颜色: 蓝色

虚函数与多态性[编辑 | 编辑源代码]

为了实现运行时多态,我们需要使用虚函数。当基类指针指向派生类对象时,虚函数确保调用的是派生类的实现:

class Animal {
public:
    virtual void makeSound() {
        cout << "动物发出声音" << endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() override {
        cout << "汪汪!" << endl;
    }
};

class Cat : public Animal {
public:
    void makeSound() override {
        cout << "喵喵!" << endl;
    }
};

void animalSound(Animal* animal) {
    animal->makeSound();
}

int main() {
    Animal a;
    Dog d;
    Cat c;
    
    animalSound(&a);
    animalSound(&d);
    animalSound(&c);
    
    return 0;
}

输出:

动物发出声音
汪汪!
喵喵!

抽象基类[编辑 | 编辑源代码]

包含至少一个纯虚函数的类称为抽象基类,不能实例化:

class AbstractClass {
public:
    virtual void pureVirtualFunction() = 0;  // 纯虚函数
};

class ConcreteClass : public AbstractClass {
public:
    void pureVirtualFunction() override {
        cout << "实现了纯虚函数" << endl;
    }
};

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

C++支持一个类继承多个基类(多重继承),但需谨慎使用以避免"菱形继承"问题:

class A {
public:
    void funcA() { cout << "A的函数" << endl; }
};

class B {
public:
    void funcB() { cout << "B的函数" << endl; }
};

class C : public A, public B {
public:
    void funcC() { cout << "C的函数" << endl; }
};

int main() {
    C c;
    c.funcA();
    c.funcB();
    c.funcC();
    return 0;
}

输出:

A的函数
B的函数
C的函数

菱形继承问题与虚继承[编辑 | 编辑源代码]

当多个派生类继承自同一个基类,然后又有一个类多继承这些派生类时,会出现菱形继承问题:

classDiagram class A class B : A class C : 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 {};

总结[编辑 | 编辑源代码]

基类与派生类是C++面向对象编程的重要概念,通过继承可以实现:

  • 代码重用
  • 层次化类设计
  • 多态行为
  • 接口抽象

理解这些概念对于构建可扩展、可维护的面向对象系统至关重要。在实际开发中,应合理使用继承,避免过度复杂的继承层次结构。