1 公有继承——is-a
继承
通过使用已有的类(基类)定义新的类(派生类),使得能够根据需要修改编程代码。
C++提供了3种继承方式——公有继承(public)、保护继承(protect)和私有继承(private)。
- 公有继承:允许派生类和外部访问。
- 保护继承:只允许派生类访问。
- 私有继承:只允许基类自己访问。
派生类继承基类的数据成员和大部分方法,但不继承基类的构造函数、析构函数和赋值操作符。
派生类可以直接访问基类的公有成员和保护成员,并能够通过基类的公有方法和保护方法访问基类的私有成员。
创建派生类对象时,程序首先调用基类构造函数,然后再调用派生类构造函数。可以使用初始化器列表句法指明要使用的基类构造函数,否则将使用默认的基类构造函数。在派生类对象过期时,程序将首先调用派生类析构函数,然后再调用基类析构函数。
class Father {
public:
Father(int a) : m_a(a) { cout << "Father constructor(int)" << endl; }
Father() : m_a(0) { cout << "Father constructor()" << endl; }
// 如果基类的析构函数不是虚函数,则在多态调用中将只调用对应于指针类型(通常为基类)的析构函数。
virtual ~Father() {}
private:
int m_a;
};
class Son : public Father {
public:
Son(int a, int b) : Father(a), m_b(b) { cout << "Son constructor(int, int)" << endl; }
Son(int b) : m_b(b) { cout << "Son constructor(int)" << endl; } // 调用基类的默认构造函数
~Son() {}
private:
int m_b;
};
int main()
{
Son s1(1, 2);
Son s2(1);
return 0;
}
/*
输出:
Father constructor(int)
Son constructor(int, int)
Father constructor()
Son constructor(int)
*/
2 多态公有继承
当需要同一个方法在派生类和基类中行为不同时,即方法的行为将取决于调用该方法的对象,此时就需要使用到多态
,其实现依赖于两个重要机制:
隐式向上强制转换使得指向基类引用或指针可以指向基类对象或派生类对象。
- 在派生类中重新定义基类的方法。
- 使用虚方法。
如果在派生类中重新定义函数,将不是使用相同的函数特征标覆盖基类声明,而是隐藏同名的基类方法,不管参数特征标如何。
但如果返回类型是基类引用或指针,则可以修改为指向派生类的引用或指针,这种特性被称为返回类型协变。
#include <iostream>
using namespace std;
class Father {
public:
virtual void say() { cout << "I'm father" << endl; }
virtual void say2(int num) { cout << "I'm father2" << endl; }
};
class Son : public Father {
public:
virtual void say() { cout << "I'm son" << endl; }
virtual void say2() { cout << "I'm son2" << endl; }
};
int main()
{
Father* person1 = new Son();
person1->say();
delete person1;
Son person2;
person2.say2();
// person2.say2(1); // 无效调用,编译报错
}
/*
输出:
I'm son
I'm son2
*/
3 抽象基类
C++通过使用纯虚函数提供未实现的函数,包含纯虚函数的类就是抽象基类
,不能创建该类的对象。
class AbstactTest {
public:
virtual void w