假设我有两个c++类:
class A
{
public:
A() { fn(); }
virtual void fn() { _n = 1; }
int getn() { return _n; }
protected:
int _n;
};
class B : public A
{
public:
B() : A() {}
virtual void fn() { _n = 2; }
};
如果我写下面的代码:
int main()
{
B b;
int n = b.getn();
}
有人可能认为n被设为2。
结果是n被设为1。为什么?
c++标准(ISO/IEC 14882-2014)说:
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 or from a
destructor, including during the construction or destruction of the
class’s non-static data members, and the object to which the call
applies is the object (call it x) under construction or destruction,
the function called is the final overrider in the constructor’s or
destructor’s class and not one overriding it in a more-derived class.
If the virtual function call uses an explicit class member access
(5.2.5) and the object expression refers to the complete object of x
or one of that object’s base class subobjects but not x or one of its
base class subobjects, the behavior is undefined.
因此,不要从构造函数或析构函数中调用试图调用正在构造或销毁的对象的虚函数,因为构造函数的顺序从基类开始到派生类,而析构函数的顺序从派生类开始到基类。
因此,试图从正在构建的基类调用派生类函数是危险的。类似地,对象以与构造相反的顺序被销毁,因此试图从析构函数调用派生类中的函数可能会访问已经释放的资源。
Firstly,Object is created and then we assign it 's address to pointers.Constructors are called at the time of object creation and used to initializ the value of data members. Pointer to object comes into scenario after object creation. Thats why, C++ do not allows us to make constructors as virtual .
.another reason is that, There is nothing like pointer to constructor , which can point to virtual constructor,because one of the property of virtual function is that it can be used by pointers only.
虚函数用于动态赋值,因为构造函数是静态的,所以我们不能将它们设为虚函数。
解决这个问题的一个方法是使用工厂方法来创建对象。
为你的类层次结构定义一个公共基类,其中包含一个虚拟方法afterConstruction():
class Object
{
public:
virtual void afterConstruction() {}
// ...
};
定义一个工厂方法:
template< class C >
C* factoryNew()
{
C* pObject = new C();
pObject->afterConstruction();
return pObject;
}
像这样使用它:
class MyClass : public Object
{
public:
virtual void afterConstruction()
{
// do something.
}
// ...
};
MyClass* pMyObject = factoryNew();
c++标准(ISO/IEC 14882-2014)说:
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 or from a
destructor, including during the construction or destruction of the
class’s non-static data members, and the object to which the call
applies is the object (call it x) under construction or destruction,
the function called is the final overrider in the constructor’s or
destructor’s class and not one overriding it in a more-derived class.
If the virtual function call uses an explicit class member access
(5.2.5) and the object expression refers to the complete object of x
or one of that object’s base class subobjects but not x or one of its
base class subobjects, the behavior is undefined.
因此,不要从构造函数或析构函数中调用试图调用正在构造或销毁的对象的虚函数,因为构造函数的顺序从基类开始到派生类,而析构函数的顺序从派生类开始到基类。
因此,试图从正在构建的基类调用派生类函数是危险的。类似地,对象以与构造相反的顺序被销毁,因此试图从析构函数调用派生类中的函数可能会访问已经释放的资源。