[C++]Call virtual member function in constructor or destructor
嗷嗷按,今天被問到在constructor/destructor中調用virtual member function的問題。答錯了,很羞恥。
依稀記得在constructor/destructor調用virtual member function不好,就隨口答道不能調用,可能會出錯。
后來仔細想想不對,羞恥呀。調用是可以的,從語言角度沒錯,只不過和其他情況下調用虛函數有些不同。
看代碼:
?
class A{
public:
A()
{
printf("\n\nclass A this = %x, *this = %x\n",this,*(int*)(this));
ff();
gg(this);
}
void gg(A*p)
{
printf("p = %x this = %x, *this = %x\n",p,this,*(int*)(this));
p->ff();
}
virtual void ff()
{
printf("A::ff()\n");
}
};
class B: public A
{
public:
B()
{
printf("\n\nclass B this = %x, *this = %x\n",this,*(int*)(this));
ff();
gg(this);
}
virtual void ff()
{
printf("B::ff()\n");
}
};
class C: public B
{
public:
C()
{
printf("\n\nclass A this = %x, *this = %x\n",this,*(int*)(this));
ff();
gg(this);
}
virtual void ff()
{
printf("C::ff()\n");
}
};
int main(){
C c;
}
?
其輸出是
class A this = 12ff60, *this = 4091ac
A::ff()
p = 12ff60 this = 12ff60, *this = 4091ac
A::ff()
?
class B this = 12ff60, *this = 4091b8
B::ff()
p = 12ff60 this = 12ff60, *this = 4091b8
B::ff()
class A this = 12ff60, *this = 4091c4
C::ff()
p = 12ff60 this = 12ff60, *this = 4091c4
C::ff()
?
三次在構造函數中調到函數ff(), 其指向的都是base類的函數,而不是派生類的函數。
對于直接在構造函數調用的ff(),比如:
?
A(){
printf("\n\nclass A this = %x, *this = %x\n",this,*(int*)(this));
ff();
gg(this);
}
?
實際上這里ff()生成的代碼是一個靜態的call, 類似call 0x123456
?
對于在其他函數中調用的ff()比如
?
void gg(A*p){
printf("p = %x this = %x, *this = %x\n",p,this,*(int*)(this));
p->ff();
}
?
p->ff()和其他情況下生成的代碼都一樣,都是 call [*this + 0],call到的還是虛函數表。
?
奧妙就在于在構造的過程中,調用base類的構造函數時,虛函數表的入口地址(*this)是變化的。
?
當然,標準中沒有規定怎么實現,具體的描述如下
Member functions, including virtual functions (10.3), can be called during construction or destruction(12.6.2). When a virtual function is called directly or indirectly from a constructor (including from themem-initializer for a data member) or from a destructor, and the object to which the call applies is theobject under construction or destruction, the function called is the one defined in the constructor ordestructor’s own class or in one of its bases, but not a function overriding it in a class derived from the constructoror destructor’s class, or overriding it in one of the other base classes of the most derived object(1.8). If the virtual function call uses an explicit class member access (5.2.5) and the object-expressionrefers to the object under construction or destruction but its type is neither the constructor or destructor’sown class or one of its bases, the result of the call is undefined.
Example:
?
代碼 class V {public:
virtual void f();
virtual void g();
};
class A : public virtual V {
public:
virtual void f();
};
class B : public virtual V {
public:
virtual void g();
B(V*, A*);
};
class D : public A, B {
public:
virtual void f();
virtual void g();
D() : B((A*)this, this) { }
};
B::B(V* v, A* a) {
f(); //calls V::f, not A::f
g(); //calls B::g, not D::g
v->g(); // v is base of B, the call is well-defined, calls B::g
a->f(); //undefined behavior, a’s type not a base of B
}
?
?
?
?
轉載于:https://www.cnblogs.com/aoaoblogs/archive/2010/09/07/1820964.html
總結
以上是生活随笔為你收集整理的[C++]Call virtual member function in constructor or destructor的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++ 字符类型总结区别wchar_t,
- 下一篇: C++中多态与虚函数的学习例子