1、override
override在英语里的原意是制服、践踏、蹂躏。在C++里中国人一般翻译为覆盖。关于override的语法都可以在书上查到。在这里就不做赘述了。但提到override以及运行时多态,就不能不讨论虚函数以及虚函数表的问题。在这里我更倾向于讨论虚函数表。这些东西肯定不是什么新的发现,但却是我自己的见解。
考虑基类Base:
class
Base
... {
public:
virtual void print1()
...{
cout << "Print1 Base!" << endl;
}
virtual void print2()
...{
cout << "Print2 Base!" << endl;
}
virtual void print3()
...{
cout << "Print3 Base!" << endl;
}
virtual void print4()
...{
cout << "Print4 Base!" << endl;
}
void speak()
...{
cout << "Speak Base!" << endl;
}
char buf[10];
} ;
... {
public:
virtual void print1()
...{
cout << "Print1 Base!" << endl;
}
virtual void print2()
...{
cout << "Print2 Base!" << endl;
}
virtual void print3()
...{
cout << "Print3 Base!" << endl;
}
virtual void print4()
...{
cout << "Print4 Base!" << endl;
}
void speak()
...{
cout << "Speak Base!" << endl;
}
char buf[10];
} ;
其中四个print函数都是虚函数。而speak函数却不是。当我们生成一个对象
Base bsObj1;
的时候,可以在调试信息中看到这个类的虚函数表。而这个对象中只有一个指向虚函数表的指针(__vfptr)。
很清楚,四个虚函数按照声明的顺序被写进了动态运行时的虚函数表。显然speak函数是不能写进这个表的。另外,虚函数表固然提供了访问其中函数的功能。但这些虚函数却并不总是通过虚函数表访问的。如果提供了足够的类型信息(说白了就是用变量名访问),就会像调用普通成员函数那样调用虚函数。例如,如下代码段生成的汇编代码:
190
: bsObj1.print1();
004013B2 lea ecx,[ebp - 50h]
004013B5 call @ILT + 215 (Base::print1) (004010dc)
004013B2 lea ecx,[ebp - 50h]
004013B5 call @ILT + 215 (Base::print1) (004010dc)