继承
final(C++11)避免被继承
class B final {};
class D : public B {};
编译后的输出是 (Visual Studio)
error C3246: “D”: 无法从“B”继承,因为它已被声明为“final”这是程序输出
派生类继承的成员
1、C++ 11派生类不继承的特殊函数:
(1)析构函数;
(2)友元函数;
2、继承基类的构造函数:
(1) using A::A; 继承所有基类ctor
(2) 不能仅继承指定的某个基类ctor
#include <iostream>
using std::cin;
using std::cout;
struct A
{
A(int i) { cout << "construct A" << std::endl; }
A(double d,int i){}
};
struct B:A
{
using A::A; //继承基类ctor,除了A(int i),因为下面的B(int i)继承了A(int i)
int d{ 0 };
B(int i) :A{ i }, d{ i }{
cout << "construct B" << std::endl;
}
};
int main(void)
{
B b(1);//先调用基类的构造函数,再调用派生类的构造函数
cin.get();
return 0;
}
多态:不同对象在接受相同消息时产生的不同动作。
C++的多态行表现在运行和编译两个阶段:
运行时:多态性通过继承和虚函数来表示
虚函数:在基类中冠以virtual的成员函数,允许在派生类中对基类的虚函数重新定义(基类中定义了虚同名函数,派生类中的同名函数自动变为虚函数);
类中保存着一个Virtual function table (虚函数表)
Run-time binding (运行时联编/动态联编)
More overhead in run-time than non-virtual function (比非虚函数开销大)
基类与派生类中有同名函数
(1) 通过派生类对象访问同名函数,是静态联编
(2) 通过基类对象的指针访问同名函数,是静态联编
(3) 通过基类对象的指针或引用访问同名虚函数,是动态联编
eg1、静态联编(对象访问):对象是什么类型,就调用什么类型
#include <iostream>
using namespace std;
class A {
public:
void f() { cout << "A" << endl; }
};
class B :public A {
public:
void f() { cout << "B" << endl; }
};
int main(void)
{
A a;
B b;
a.f();//A::f
b.f();//B::f
return 0;
}
eg2:静态联编(指针访问):指针是什么类型,就调用什么类型
#include <iostream>
using namespace std;
class A {
public:
void f() { cout << "A" << endl; }
};
class B :public A {
public:
void f() { cout << "B" << endl; }
};
int main(void)
{
A a; B b; A* ptr;
ptr = &a; (*ptr).f();//A
ptr = &b; (*ptr).f();//A
return 0;
}
eg3:动态联编:只看对象
(1)虚函数指针
#include <iostream>
using namespace std;
class A {
public:
virtual void f() { cout << "A" << endl; }
};
class B :public A {
public:
void f() { cout << "B" << endl; }
};
int main(void)
{
A a; B b; A* ptr;
ptr = &a; (*ptr).f();//A
ptr = &b; (*ptr).f();//B
return 0;
}
(2)虚函数引用
#include <iostream>
using namespace std;
class A {
public:
virtual void f() { cout << "A" << endl; }
};
class B :public A {
public:
void f() { cout << "B" << endl; }
};
int main(void)
{
A a; B b;
A& p1 = a;
A& p2 = b;
p1.f();
p2.f();
return 0;
}
纯虚函数:在基类中为其派生类保留一个函数的名字,以便派生类对其进行定义。不允许直接调用纯虚函数
从基类继承来的纯虚函数,在派生类中仍是虚函数,一个类至少有一个纯虚函数,这个类称为抽象类,抽象类必须用作派生其他类的基类,不能直接创建对象。