开发日志系列(十一)
目前我参与的项目中使用了大量的接口调用,大量的继承(多重继承,多重派生等),其中的大部分都是使用了C++语言的动态绑定
特性.既然有动态绑定,哪就相应的肯定有静态绑定
,今晚复习了下这个特性.
静态绑定与动态绑定
静态绑定又名前期绑定(early binding),绑定的是对象的静态类型发生在编译期.动态绑定又名后期绑定(late binding),绑定的是对象的动态类型,发生在运行期.简单的说就是:静态绑定在编译完成后已经确定,动态绑定则需要在运行的时候才确定.考虑如下继承:
class B{ public: void testA(){printf("class B testA()\n");}; virtual void testB(){printf("class B testB()\n");}; }; class D:public B{ public: void testA(){printf("class D testA()\n");}; virtual void testB(){printf("class D testB()\n");}; }; int main(int argc, const char * argv[]) { // insert code here... D x; B* pB = &x; D* pD = &x; printf("testing non-virturl\n"); pB->testA(); pD->testA(); printf("testing virturl\n"); pB->testB(); pD->testB(); return 0; }
运行后输出如下:
testing non-virturl class B testA() class D testA() testing virturl class D testB() class D testB()
pB,pD虽然都指向派生类D,但是调用non-virtual函数(非虚成员函数)的时候pB调用到基类B的定义.调用virtual函数(虚函数)的时候则均是调用到派生类D的定义.
原因在于:
非虚函数属于静态绑定,所以类B或者D 指针调用非虚函数的时候 均是调用到自身的定义.
虚函数属于动态绑定,无论指针类型是基类B还是派生类D,调用到的都取决于调用的那个对象的类型.
往后C++编程中应当避免
- 重新定义非虚成员类
- 多重继承中的指针频繁转换
- 接口基类不应该有非虚函数(也就是全部设置位纯虚函数)
这篇日志系Effective C++读书笔记,参考其中第36,37条款.
这本书不错。。
@高军, 慢慢看才有味道~
@Rect, 有本叫什么陷阱的推荐下