建構函式語義學——Copy Constructor 的構造操作
前言
在三種情況下,會以一個 object 的內容作為另一個 class object 的初值:
- object明確初始化
class X{...};
X x;
X xx = x;
- object 被當作引數交與某個函式
extern void foo(X x);
void bar(){
X xx;
foo(xx);//作為第一個引數的初值(不明顯的初始化)
}
- 函式返回值是一個 class object
X foo_bar(){
X xx;
...
return xx;
}
如果開發者已經明確定義了一個copy constructor 如下:
//copy constructor可以是多引數,其中有一個引數是其class type X::X(const X& x); Y::Y(const Y& y);
那麼在大部分情況下,當 class object 以另一個同類實體作為初值時,上述 constructor 會被呼叫,這可能會導致一個暫時性 class object 的產生或程式程式碼發生改變(或二者都有)。
重新設定 Virtual Table 的指標
編譯期間的擴張操作(只要有一個class聲明瞭一個或多個virtual function):
增加一個 virtual function table(vtbl),內含每一個有作用的 virtual function 的地址。
一個指向 virtual function table 的指標(vptr),安插在每個 class object 內。
如果編譯器對每個新產生的 class object 的 vptr 不能正確的設定初值,則會出錯。因此,當編譯器匯入 vptr 到 class 中時,該 class 不再展現 bitwise semantics。而是合成一個 copy constructor 來使得 vptr 正確初始化,下面是個例子:
class ZooAnimal{ public: ZooAnimal(); virtual ~ZooAnimal(); virtual void animate(); virtual void draw(); private: ...//some data }; class Bear : public ZooAnimal{ public: Bear(); void animate(); void draw(); private: ...//some data };
ZooAnimal class object 以另一個 ZooAnimal class object 為初值,或 Bear class object 以另一個 Bear class object 為初值,都可以直接靠 bitwise copy semantics 完成。在這種情況下,vptr保持bitwise copy是安全的。
當一個 base class object 以其 derived class object 內容作初始化操作時,其 vptr 也需要保證安全:
Bear B; ZooAnimal Z = B;//sliced
顯然,Z的 vptr 不應該指向 Bear 的 vtbl,也就是說,Base class 被合成出來的copy constructor會明確設定 object 的 vptr 指向 Base Class 的 vtbl,而非從 rhs 處執行 bitwise copy。