📜  C++中的派生数据类型(1)

📅  最后修改于: 2023-12-03 15:29:54.570000             🧑  作者: Mango

C++中的派生数据类型

在C++中,派生数据类型是通过继承一个或多个现有类(基类)和添加一些新的成员来定义的。派生数据类型是基于现有类型生成的,这使得派生数据类型可以复用现有类型的代码和功能。

基本概念

C++中的类可以被继承,派生类可以像基类一样访问基类的公共和受保护成员,同时也可以添加新的成员。派生类可以是单继承或多继承。

派生类的声明方式为:

class DerivedClass : accessSpecifier BaseClass {};

其中,accessSpecifier可以是public、protected或private,用来指定基类成员的访问权限。

单继承

单继承是指派生类只继承了一个基类。例如:

class Shape {
public:
    void setWidth(int w) {
        width = w;
    }
    void setHeight(int h) {
        height = h;
    }
protected:
    int width;
    int height;
};

class Rectangle : public Shape {
public:
    int getArea() {
        return width * height;
    }
};

int main() {
    Rectangle rect;
    rect.setWidth(5);
    rect.setHeight(3);
    cout << "Area: " << rect.getArea() << endl;
    return 0;
}

在上面的例子中,Rectangle类继承了Shape类,并添加了getArea()函数计算矩形的面积。Rectangle类可以访问基类Shape的width和height成员。

多继承

多继承是指派生类同时继承了两个或更多的基类。例如:

class Animal {
public:
    void eat() {
        cout << "I can eat." << endl;
    }
};

class WingedAnimal {
public:
    void flapWings() {
        cout << "I can flap my wings." << endl;
    }
};

class Bat : public Animal, public WingedAnimal {
public:
    void echoLocation() {
        cout << "I can echolocate." << endl;
    }
};

int main() {
    Bat bat;
    bat.eat();          // I can eat.
    bat.flapWings();    // I can flap my wings.
    bat.echoLocation(); // I can echolocate.
    return 0;
}

在上面的例子中,Bat类同时继承了Animal类和WingedAnimal类,Bat类可以访问这两个基类的成员函数。

虚继承

虚继承是指基类被多个派生类继承时,通过关键字virtual只产生一个共享的基类子对象。例如:

class Animal {
public:
    void eat() {
        cout << "I can eat." << endl;
    }
};

class WingedAnimal : virtual public Animal {
public:
    void flapWings() {
        cout << "I can flap my wings." << endl;
    }
};

class Bat : virtual public Animal, public WingedAnimal {
public:
    void echoLocation() {
        cout << "I can echolocate." << endl;
    }
};

int main() {
    Bat bat;
    bat.eat();          // I can eat.
    bat.flapWings();    // I can flap my wings.
    bat.echoLocation(); // I can echolocate.
    return 0;
}

在上面的例子中,WingedAnimal类和Bat类都是通过虚继承继承自Animal类的,这样就避免了Animal类的成员被多次继承产生的冗余。

特殊成员函数

派生类中通常也需要定义构造函数、析构函数和赋值运算符等特殊成员函数。其中,构造函数和析构函数需要在派生类中初始化基类的成员,赋值运算符需要注意调用基类的赋值运算符。

例如:

class Base {
public:
    Base() {
        // ...
    }
    virtual ~Base() {
        // ...
    }
    Base& operator=(const Base& other) {
        if (this != &other) {
            // ...
        }
        return *this;
    }
};

class Derived : public Base {
public:
    Derived() :
        Base() {
        // ...
    }
    virtual ~Derived() {
        // ...
    }
    Derived& operator=(const Derived& other) {
        if (this != &other) {
            Base::operator=(other); // 调用基类的赋值运算符
            // ...
        }
        return *this;
    }
};