C++快速入门之virtual
virtual
为什么需要virtual,因为C++选择了优先静态绑定,所以需要一个特别的关键字来告诉编译器这个函数需要动态绑定(动态绑定通常就是所谓的“多态”)。
为什么Object-C没有这样的关键字?因为据我所知,Object-C等语言选择了动态绑定,所以它们没有像C++里面的静态绑定函数(不带virtual的),
所以就不需要这个关键字。大体上相当于其函数都是virtual的……
从语言风格上说,C++讲究的是对最终实现的极致把握。普通的类成员函数在调用时,直接执行相应内存地址的代码即可。
但如果有多态,那么实现起来需要维护一个表,在运行时动态根据对象的类型决定使用哪部分代码。这两者是有性能差异的。
C++允许你根据需要选择最快的实现方式。ObjC完全是考虑程序员的方便,面向对象部分用起来几乎就已经是“动态”语言了。
它通过消息传递实现类函数的调用,非常灵活。开销相比于C++是大不少的,但它不关心这点儿开销。
实例1
#include <iostream>
using namespace std;
class Base {
public:
Base() {}
public:
virtual void print() { cout << "Base"; }
};
class Derived : public Base {
public:
Derived() {}
public:
void print() { cout << "Derived"; }
};
int main() {
Base *point = new Derived();
point->print();
delete point;
}
实例2
class ClxBase {
public :
ClxBase() {};
virtual ~ ClxBase() {};
virtual void DoSomething() {
cout << "Do something in class ClxBase ! " << endl;
};
};
class ClxDerived : public ClxBase {
public :
ClxDerived() {};
~ ClxDerived() {
cout << "Output from the destructor of class ClxDerived!" << endl;
};
void DoSomething() {
cout << "Do something in class ClxDerived ! " << endl;
};
};
int main() {
ClxBase *pTest = new ClxDerived;
pTest->DoSomething();
delete pTest;
}
这个很简单,非常好理解。
但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:
Do something in class ClxDerived!
也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。
我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。
所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。
所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!