一、虚函数、纯虚函数的定义
虚函数:虚函数用于实现C++多态机制,核心理念就是通过基类使用派生类定义的函数,所谓虚函数就是在基类定义一个未实现的函数名,为了提高代码的可读性,建议将后代的虚函数都加上virtual关键字。
纯虚函数:纯虚函数是在基类中声明的虚函数,他在基类中没有定义但要求在派生类中定义自己的实现方法。在基类中实现纯虚函数的方法就是在函数原型后加“=0”,纯虚函数不能实例化对象。
一般格式:
class Season{
public:
Season();
virtual void Clothing() const = 0; //定义纯虚函数
};
class Spring: public Season{
public:
virtual void Clothing(){
std::cout<<"春天穿夹克"<<endl;
}
};
class Summer: public Season{
public:
virtual void Clothing(){
std::cout<<"夏天穿短袖"<<endl;
}
};
int main(){
Spring March;
Summer June;
Season *seasons[] = {& March, &June};
for(auto pSeason:seasons){
pSeason->Clothing();
}
}
解释一下上述例子,Season是一个通用基类,但是我们仍希望存在一个Clothing函数,这样我们就可以在不知道Season类型的情况下,在Season上调用Clothing函数,仅在编译时我们才能知道Season的类型,因此我们在基类中声明虚函数Clothing(),并用=0来表示是由派生类来实现的纯虚函数。
然后再用Spring和summer来真正实现该函数,当我们熟练使用虚函数后,可以在实现时加上override使编译器确保函数签名与基类中的签名相匹配。
//使用override确保签名匹配
virtual void Clothing() const override{
std::cout<<"春天穿夹克"<<endl;
}
二、协变式返回类型
我们提到过,若要实现虚函数,派生类函数的签名必须与基类中的签名相匹配。 唯一允许的区别是在返回类型上,只要派生类的返回类型是基类返回的派生类型即可。
三、抽象类的介绍
抽象类是一种特殊的类,它是为了抽象和设计为目的建立的,处在派生类的较上层。
(1)抽象类的定义:我们称带有纯虚函数的类为抽象类
(2)抽象类的作用:抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。所以派生类实际上刻画了一组子类的操作接口的通用语义,这些语义也传给子类,子类可以具体实现这些语义,也可以再将这些语义传给自己的子类。
四、总结
- 纯虚函数的声明如下:virtual void vfun() const = 0; 纯虚函数一定没有定义,纯虚函数用来规范派生类的行为,即为接口。包含纯虚函数的类是抽象类,抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。
- 虚函数必须实现,否则编译会报错。
- 对于虚函数来说,子类和父类都有各自的版本,由多态的方式调用的时候进行动态绑定。
- 实现了纯虚函数的子类,该纯虚函数在子类中就编程了虚函数,子类的子类即孙子类可以覆盖该虚函数,由多态方式调用的时候动态绑定。
- 虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。
- 在有动态分配堆上内存的时候,析构函数必须是虚函数,但没有必要是纯虚的。