个简单的指针,此时多重继承将不需要任何空间上的额外负担!slots中的地址可以直接指向virtual function,也可以指向一个相关的thunk。
4.3函数的效能
nonmember、static member和nonstatic member function在内部都会转化为完全相同的形式,三者效率相同。
2002-08-08
4.4指向Member Function的指针
对一个nonstatic member function取址,得到的是该函数在内存中的地址;而面对一个virtual function,得到的将是一个索引值。这个值是不完整的,必须被绑定于一个class object上,才能够通过它调用函数。指向member function的指针的声明语法,以及指向member selection运算符的指针,其作用是作为this指针的空间保留者。因此,static member function的类型是函数指针,而不是指向member function的指针。
使用一个member function指针,如果并不用于virtual function、多重继承、virtual base class等情况的话,其成本并不比使用一个nonmember function指针要高。
4.5 Inline Functions
关键词inline只是一项请求。如果在某个层次上,函数的执行成本比一般的函数调用及返回机制所带来的负荷低,那么该请求被接受,编译器就用一个表达式合理地将函数扩展开来。真正的inline函数扩展操作是在函数调用的那一点上。在inline扩展期间,每一个形式参数会被对应的实际参数所取代,inline函数中的每一个局部变量都必须被放在函数调用的一个封闭区段中,并拥有一个独一无二的名称。这会带来参数的求值操作以及临时性对象的管理。
2002-08-11
构造、解构、拷贝语意学Semantics of Construction, Destruction, and Copy
1.一般而言,class的data member应该被初始化,而且只在constructor中或其它member functions中初始化,其它任何操作都将破坏其封装性质,使其维护和修改更加困难。
2.可以定义并调用invoke一个pure virtual function,但它只能被静态调用,不能经由虚拟机制调用。每一个derived class destructor会被编译器加以扩展,静态调用每一个virtual base class以及上一层base class的destructor。因此,不管base class的virtual destructor是否声明为pure,它必须被定义。
5.1无继承情况下的对象构造
C++ Standard要求编译器尽量延迟nontrivial members的实际合成操作,直到真正遇到其使用场所为止。
5.2继承体系下的对象构造
一般而言,继承体系下编译器对constructor所作的扩充操作以及次序大约如下:
ü所有virtual base class constructors必须从左到右、从深到浅被调用:如果class被列于member initialization list中,那么任何明确指定的参数都必须传递过去,否则如果class有一个default constructor,也应该调用它;class中的每一个virtual base class subobject的偏移量offset必须在执行期可被存取;如果class object是最底层most-derived的class,其constructors可能被调用,某些用以支持这个行为的机制必须被方进来。
ü以base class的声明次序调用上一层base class constructors:如果base class被列于member initialization list中,那么任何明确指定的参数都必须传递过去,否则若它有default constructor或default memberwise copy constructor,那么就调用它;如果base class是多重继承下的第二或后继的base class,那么this指针必须有所调整。
ü如果class object有virtual table pointer(s),它(们)必须被设定初值,指向适当的virtual table(s)。
ü如果有一个member没有出现在member initialization list中,但它有default constructor,调用之。
ü将member initialization list中的data members的初始化操作以members的声明次序放进constructor的函数本身。
2002-8-18
5.3对象复制语意学Object Copy Semantics
1.只有在默认行为所导致的语意不安全或者不正确以致发生别名化aliasing或者内存泄漏memory leak时,才需要设计一个copy assignment operator。否则,程序反倒会执行得较慢。
2.如果仅仅是为了把NRV优化开关打开而提供一个copy constructor,那么就没有必要一定要提供一个copy assignment operator。
3.copy assignment operator有一个非正交情况,那就是它缺乏一个平行于member initialization list的member assignment list。调用base class的copy assignment operator示例:
Point::operator = (p3d);或(*(Point*)this) = p3d;或(Point &)(*this) = p3d;
4.事实上,copy assignment operator在虚拟继承情况下行为不佳,需要小心设计和说明。许多编译器甚至并不尝试取得正确的语意,它们在每一个中间的copy assignment operator中调用每一个base class instance,于是造成virtual base copy assignment operator的多个实体被调用。建议尽可能不要允许一个virtual base class的拷贝操作,并不要在任何virtual base class中声明data member。
5.5解构语意学Semantics of Destruction
如果class没有定义destructor,那么只有在其内带的member object或base class拥有destructor时,编译器才会自动合成出一个destructor。一个由程序员定义的destructor被扩展的方式类似constructors被扩展的方式,只是顺序相反:
üdestructor的函数本体首先被执行;
ü如果class拥有member class objects,而后者拥有destructors,那么它们将以声明的相反顺序而调用;
ü如果object内带一个vptr,则现在被重新设定以指向适当base class之virtual table;
ü如果有任何直接的nonvirtual