虚函数
是实现多态
特性的重要工具。下面看一个例子体会一下:
class base {
public:
virtual void show() { std::cout << "base" << std::endl; };
virtual ~base() { std::cout << "base destruct" << std::endl; }
};
class derive : public base {
public:
void show() { std::cout << "derive" << std::endl; };
~derive() { std::cout << "derive destruct" << std::endl; }
};
int main(void) {
derive der;
base *d = &der;
d->show();
std::cout << "exit" << std::endl;
}
输出:
derive
exit
derive destruct
base destruct
通过基类
的指针指向派生类
的地址,在调用基类
对象时,动态选择其真实类型关联的函数,从而实现多态特性
。
-
构造函数为什么不能是虚函数?
虚函数
的主要目的是通过基类
的指针或引用,调用派生类
关联的函数,实现多态
特性。而构造函数是在初始化一个对象时调用的,派生类
此时并没有完全构造出来(调用构造函数前),也没有与对应的基类
指针或引用关联起来,没有办法使用多态
特性。构造函数是虚函数
没有必要。 -
虚构函数为什么可以是虚函数?
因为释放堆上内存时可能通过
基类
的指针进行delete
,如果析构函数不是虚函数
,则会调用基类的析构函数,派生类
就得不到正确的销毁,造成内存泄露。一般在使用多态
特性时,基类
的析构函数都应是虚函数
。 -
虚函数的默认参数是静态绑定的。即,通过基类的指针访问派生类时,传入的是基类的默认参数,而不是派生类的默认参数。
-
虚函数可以是私有的,只要在动态绑定时能绑定即可。例如:基类的虚函数是私有的,派生类的虚函数是公有的,则通过基类的指针或引用访问派生类的方法时,并不会存在找不到函数的错误。
纯虚函数
纯虚函数
简单来说就是没有定义的虚函数
。写法就是在虚函数
后添加= 0
修饰。下面看一个例子:
class base {
public:
virtual void show() = 0;
virtual ~base() { std::cout << "base destruct" << std::endl; }
};
class derive : public base {
public:
void show() { std::cout << "derive" << std::endl; };
~derive() { std::cout << "derive destruct" << std::endl; }
};
int main(void) {
derive der;
base *d = &der;
d->show();
std::cout << "exit" << std::endl;
}
那纯虚函数
有什么用呢?纯虚函数
一般用于实现抽象类
。那什么是抽象类
呢?抽象类
简单来说就是接口
,通过定义一些共同行为
的集合,对派生类
进行约束。当然抽象类
也可以有数据成员。那抽象类有什么特点呢?
- 抽象类不能实例化,一般使用指针或引用实现
多态
特性。 - 只要有一个
纯虚函数
,该类就是抽象类。 - 抽象类的所有虚函数(析构函数除外),必须在
派生类
中实现,才能成为非抽象类
,否则派生类
也是抽象类
。 抽象类
可以有构造函数。抽象类
的构造函数一般被派生类
调用,初始化抽象类
的数据成员。