菱形继承 虚继承 (virtual)
class A
{
public:
int n;
};
class A_1 : virtual public A
{
public:
int a1;
};
class A_2 : virtual public A
{
public:
int a2;
};
class AA : public A_1,A_2
{
public:
};
一 联编
处理函数调用的过程
一 含义
-
静态联编:编写代码阶段,早期联编,静态约束
-
动态联编:程序运行阶段,晚期联编,动态约束
二 多态
不同对象,调用同一个函数,有不同的功能
一 要求
-
必须存在继承关系
-
父子类必须有同名虚函数(其中虚函数是在基类中使用关键字Virtual声明的函数,在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数)
-
存在基类类型的指针或者引用,通过该指针或引用调用虚函数
二 虚函数
-
纯虚函数声明如下: virtual void funtion1()=0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即接口。包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用
-
虚函数声明如下:virtual ReturnType FunctionName(Parameter) 虚函数必须实现,如果不实现,编译器将报错,错误提示为:
error LNK****: unresolved external symbol "public: virtual void __thiscall ClassName::virtualFunctionName(void)"
-
对于虚函数来说,父类和子类都有各自的版本。由多态方式调用的时候动态绑定。
-
实现了纯虚函数的子类,该纯虚函数在子类中就编程了虚函数,子类的子类即孙子类可以覆盖该虚函数,由多态方式调用的时候动态绑定。
-
虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。
-
在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。
-
友元不是成员函数,只有成员函数才可以是虚拟的,因此友元不能是虚拟函数。但可以通过让友元函数调用虚拟成员函数来解决友元的虚拟问题。
-
析构函数应当是虚函数,将调用相应对象类型的析构函数,因此,如果指针指向的是子类对象,将调用子类的析构函数,然后自动调用基类的析构函数。
三 特点
-
虚函数表(虚函数的首地址)
-
虚指针 指向虚函数表
-
虚函数表不会被继承,但虚函数会被继承
四 实例
#include<iostream>
using namespace std;
class Animal{
public:
//1 在父类中 声明虚函数
virtual void speak()
{
cout << "HAPPY NEW YEAR" << endl;
}
//3 虚析构
virtual ~Animal()
{
cout << "父类析构" << endl;
}
};
class Sheep : public Animal{
public:
//2 在子类中 声明一个和父类同名的虚函数
//重写父类的虚函数
virtual void speak(); //p_ani_2->speak();
};
void Sheep::speak()
{
cout << "新年快乐" << endl;
}
int main()
{
Animal* p_ani_1 = new Animal;
Animal* p_ani_2 = new Sheep;
p_ani_1->speak();
p_ani_2->speak();
delete p_ani_2;
return 0;
}
三 纯虚函数
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;
};
class Rectangle : public Shape {
public:
virtual int area(){}
}
一 抽象类
-
包含纯虚函数的类是抽象类,抽象类不能实例化对象,但可以声明指向实现该抽象类的具体类的指针或引用
-
纯虚类:类里面函数全是纯虚函数
四 终结者(final)
一 函数
class Animal{
public:
//1 在父类中 声明虚函数
virtual void speak() final
{
cout << "HAPPY NEW YEAR" << endl;
}
//3 虚析构
virtual ~Animal()
{
cout << "父类析构" << endl;
}
};
class Sheep : public Animal{
public:
//virtual void speak(); ① 已被终结,无法重写
};
二 类
class Animal final
{
};
/*
class Sheep : public Animal ② 已被终结,Animal无法产生子类
{ };
*/