class Base {
public:
Base() = default;
Base(int x):num(x){}
~Base() = default;
virtual int getNum()
{
return num;
}
private:
int num;
};
class Derive : public Base
{
public:
Derive() = default;
//派生类构造函数只初始化它的直接基类。
Derive(int x,int y) : Base(x), der_num(y){}
~Derive() = default;
//为虚函数,可以使用virtual修饰,也何以不使用,因为被定义为虚函数后在所有的派生类中都是虚函数。
//派生类中的虚函数的形参和返回类型必须和基类中的相同,除返回的是类本身的指针或引用外。
int getNum()
{
return der_num;
}
private:
int der_num;
};
void showNum(Base& base)
{
cout << base.getNum() << endl;
}
int main()
{
//在使用虚函数时必须为每一个虚函数提供定义,因为动态绑定的原因,编译器在使用虚函数时不确定使用哪个。
//因此虚函数的调用可能在运行时才被解析。
Base base(7);
showNum(base);//调用的Base的
Derive derive(9, 8);
showNum(derive);//调用的Driver的
base = derive;
showNum(base);//调用的是Driver赋值的Base
override和final
//使用override可以来说明派生类中的虚函数,此时该虚函数必须要在派生类中被覆盖
struct Str_A
{
virtual void f1(int) const;
virtual void f2();
void f3();
virtual void f4(int) const;
};
struct Str_B : Str_A
{
void f1(int)const override;//正确 f1与基类中的匹配。
//void f2(int) override;//错误 基类中的f2没有形参,因为不匹配所以派生类中的f2没有匹配基类中的f2。
//void f3() override;//错误 f3不是虚函数。
};
//使用final,则在之后的派生类中不能覆盖基类中的该虚函数。
struct Str_C : Str_A
{
void f4(int) const final;//正确 正常覆盖了Str_A中的f4,但之后的派生类不能再覆盖了。
};
struct Str_D : Str_C
{
void f4();//正确,因为不匹配,所以没有覆盖
//void f4(int) const;//错误 类型匹配,虚函数f4以不允许覆盖。
};
//虚函数可以拥有默认实参,派生类中的虚函数实参最好与基类中的一致,不然可能会出现问题。
//可以使用域作用符强行指定执行特定的版本的虚函数,避免了动态绑定。
Derive *derive_1;
derive_1->Base::getNum();
纯虚函数
//一个纯虚函数无须定义
//在虚函数定义时,将其使用=0来定义,该虚函数就是纯虚函数。
//=0只能出现在类内部的虚函数声明语句处。
//virtual int fun(int) const = 0;
抽象基类
//含有纯虚函数的类是抽象基类
//不能定义抽象基类的对象
struct Str_Chou
{
virtual void fun() = 0;
};
//Str_Chou chou;//错误 Str_Chou为抽象基类
return 0;
}