#include <stdio.h>
class A {
public:
virtual void print() = 0;
A() { printf("%s %d enter\n", __func__, __LINE__); }
};
class B : public A {
public:
B() { printf("%s %d enter\n", __func__, __LINE__); }
};
class C : public B {
public:
virtual void print() { printf("hello\n"); }
C() { printf("%s %d enter\n", __func__, __LINE__); }
};
int main()
{
C c; // 正确
// B b; // 错误
// A a; // 错误
return 0;
}
运行后的打印:
A 7 enter
B 12 enter
C 19 enter
当去掉26行注释,编译报错:
test_2.cpp: In function ‘int main()’:
test_2.cpp:26:4: error: cannot declare variable ‘b’ to be of abstract type ‘B’
26 | B b; // 错误
| ^
test_2.cpp:10:7: note: because the following virtual functions are pure within ‘B’:
10 | class B : public A {
| ^
test_2.cpp:5:15: note: ‘virtual void A::print()’
5 | virtual void print() = 0;
| ^~~~~
总结:
在上面的示例中,有A、B、C三个类,其中A是一个包含virtual虚函数的抽象类,
B类继承A类但不实现虚函数,C类继承B类且实现了虚函数。
- 一个类(B类)如果继承了含有虚函数的抽象类(A类),则 子类(B类)同样是抽象类,是无法实例化的,尝试对其实例化则会编译时报错;
- 子类(C类)实例化,构造顺序是先基类部分、后子类部分(先后顺序是A->B->C);
- 子类(C类)实例化时,虽然调用到了基类(B类)的构造函数,但只是构造子类中的基类部分,并非构造一个B类型的对象,所以不会报1中的编译错误。