首页 > 试题广场 >

构造函数中可以调用虚函数吗?

[问答题]
参见《Effective C++》 条款09:绝不在构造函数或析构函数中调用虚函数。
这个链接有电子档:http://blog.csdn.net/hxz_qlh/article/details/14089895

简要结论:
1. 从语法上讲,调用完全没有问题。
2. 但是从效果上看,往往不能达到需要的目的。
Effective 的解释是:
派生类对象构造期间进入基类的构造函数时,对象类型变成了基类类型,而不是派生类类型。
同样,进入基类析构函数时,对象也是基类类型。

所以,虚函数始终仅仅调用基类的虚函数(如果是基类调用虚函数),不能达到多态的效果,所以放在构造函数中是没有意义的,而且往往不能达到本来想要的效果。

编辑于 2016-08-03 18:45:29 回复(0)
可以,但不会达到预期的效果
父类先于子类被构造,当父类中的构造函数被调用时,子类还没有形成,此时子类对于编译器来说是不存在的,所以调用的仍是父类本身的虚函数。
发表于 2015-07-27 19:37:43 回复(0)
  1. class  Base  
  2. {  
  3. public :  
  4.     Base()  
  5.     {  
  6.         Fuction();  
  7.     }  
  8.   
  9.     virtual   void  Fuction()  
  10.     {  
  11.         cout << "Base::Fuction"  << endl;  
  12.     }  
  13. };  
  14.   
  15. class  A :  public  Base  
  16. {  
  17. public :  
  18.     A()  
  19.     {  
  20.         Fuction();  
  21.     }  
  22.   
  23.     virtual   void  Fuction()  
  24.     {  
  25.         cout << "A::Fuction"  << endl;  
  26.     }  
  27. };  
  28.   
  29. // 这样定义一个A的对象,会输出什么?   
  30. A a;  
  31. class Base
    {
    public:
    	Base()
    	{
    		Fuction();
    	}
    
    	virtual void Fuction()
    	{
    		cout << "Base::Fuction" << endl;
    	}
    };
    
    class A : public Base
    {
    public:
    	A()
    	{
    		Fuction();
    	}
    
    	virtual void Fuction()
    	{
    		cout << "A::Fuction" << endl;
    	}
    };
    
    // 这样定义一个A的对象,会输出什么?
    A a;

        首先回答标题的问题,调用当然是没有问题的,但是获得的是你想要的结果吗?或者说你想要什么样的结果?

        有人说会输出:


  1. A::Fuction  
  2. A::Fuction  
A::Fuction
A::Fuction

        如果是这样,首先我们回顾下C++对象模型里面的构造顺序,在构造一个子类对象的时候,首先会构造它的基类,如果有多层继承关系,实际上会从最顶层的基类逐层往下构造(虚继承、多重继承这里不讨论),如果是按照上面的情形进行输出的话,那就是说在构造Base的时候,也就是在Base的构造函数中调用Fuction的时候,调用了子类A的Fuction,而实际上A还没有开始构造,这样函数的行为就是完全不可预测的,因此显然不是这样,实际的输出结果是:


  1. Base::Fuction  
  2. A::Fuction  
发表于 2015-05-07 02:21:17 回复(1)
详见C++ primer 第五版 P556->在构造函数和虚构函数中调用虚函数。
编辑于 2017-11-30 21:09:57 回复(0)
亲测可以,但是此时的虚函数和普通函数没有区别了。
发表于 2017-05-20 16:04:15 回复(0)
可以的,但是先调用父类构造函数,再调用子类构造函数,各自调用各自版本的函数
发表于 2015-08-13 19:21:18 回复(0)
可以,但是其构造函数中调用的仍是自己的虚函数,没有达到延迟绑定的效果。
发表于 2015-07-27 09:13:10 回复(0)
可以,但是没有意义,没有实现动态绑定的效果
发表于 2015-07-10 10:17:10 回复(0)
答案:可以,但是没有意义,父类的构造函数中调用的是父类的虚函数,在子类中调用的是子类的虚函数。
发表于 2015-06-18 19:30:51 回复(0)
可以的,但是没有意义,虚函数是为了实现多态,在父类构造函数中调用的是父类的虚函数,在子类中调用的是子类的虚函数
发表于 2015-06-06 09:47:12 回复(0)
可以,但是没有动态绑定的效果,父类构造函数中调用的仍然是父类版本的函数,子类中调用 的仍然是子类版本的函数
发表于 2015-05-05 14:31:24 回复(0)