继承

访问控制

使用:进行继承,有三种继承的方式public,protected,private,被继承的类叫做基类,继承基类的类叫做派生类

publicprotectedprivate 是三种访问控制修饰符,用于控制成员在类的内部和外部的可见性和可访问性,public在类的内外都可以访问,protected在类的外部不可访问,在子类中可以直接访问,但子类中不能通过对象名对protected进行访问,private在子类中也不可访问

  • public:基类的public成员在派生类中仍为public,积累的protected成员在派生类中仍是protected,基类的private成员为private
  • protected:基类的public成员在派生类中变成protected,积累的protected成员在派生类中仍为protected,积累的private成员为private
  • private:基类的public和protected成员在派生类中都变成private

继承中的构造函数和析构函数

创建子类会先调用父类的构造函数

子类不能继承父类的构造函数,但可以显式调用父类的构造函数,如果没有调用基类的构造函数,基类的默认构造函数会在子类的构造函数之前自动调用,如果基类没有默认构造函数,子类必须通过:BaseClass()的方式显示调用基类的构造函数

销毁子类会先调用子类的析构函数

当对象被销毁时,子类的析构函数会首先被调用,然后基类的析构函数会被调用,析构函数的调用顺序和构造函数的调用顺序相反

多态和虚函数

通过使用虚函数(virtual),可以在基类中定义一个接口,并在派生类中重写该接口的实现,这样,基类指针或引用可以指向派生类对象,并调用派生类的重写方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Base {
public:
virtual void show() {
std::cout << "Base class show function" << std::endl;
}
};

class Derived : public Base {
public:
void show() override {
std::cout << "Derived class show function" << std::endl;
}
};

int main() {
Base* basePtr = new Derived();
basePtr->show(); // 输出:Derived class show function
delete basePtr;
return 0;
}

对于虚函数,在基类中有了实现,那么子类不一定必须进行重写,如果没有重写,就会调用父类中的虚函数。而基类中没有实现的虚函数叫做纯虚函数,使用=0表示该函数时虚函数,纯虚函数强制派生类必须提供该函数的实现,含有纯虚函数的类时抽象类,无法实例化

多重继承

c++支持多重继承,即一个类可以从多个基类继承。

在多重继承中,如果基类中有相同名称的函数,派生类需要显示指定调用的哪一个基类的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Base1 {
public:
void show() {
std::cout << "Base1 class show function" << std::endl;
}
};

class Base2 {
public:
void show() {
std::cout << "Base2 class show function" << std::endl;
}
};

class Derived : public Base1, public Base2 {
};

int main() {
Derived obj;
obj.Base1::show(); // 调用 Base1 的 show()
obj.Base2::show(); // 调用 Base2 的 show()
return 0;
}

虚继承

当多重继承中多个基类继承自同一个祖先类时,可能会发生“菱形继承”——祖先类的成员在派生类中出现多次,为了解决这个问题,C++提供了虚继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A {
public:
int value;
};

class B : virtual public A {
};

class C : virtual public A {
};

class D : public B, public C {
};

int main() {
D obj;
obj.value = 10; // 通过虚继承,`value` 只继承一次
return 0;
}