再来一道网易的C++题目

2013年4月11日 由 Creater 留言 »

还是先上代码

#include <iostream>
using namespace std;

class A
{
public:
    A(int j):i(j)
    {
        fun1();           //在构造函数中调用了虚函数
    }
    ~A()
    {
    }
    void fun1()
       {
           i *= 10;
           fun2();
       }
    int getValue(){
    	return i;
    }
protected:
    virtual void fun2()
    {
        i++;
    }
private:
    int i;
};

class B:public A
{
public:
    B(int j):A(j)
    {
    }
    virtual ~B()
    {
    }
    void fun1()
      {
          i *= 100;
          fun2();
      }
protected:
    void fun2()
    {
        i += 2;
    }
private:
    int i;
};
int main()
{
     A* p = new B(1);
     cout<<p->getValue()<<endl;
     delete p;
     return 0;
};


你看来答案是多少呢?反正我是算错了,但是我搞清了原因,争取下一次不出错。“答案是11”.

先来看看执行顺序。首先 new B(1)–>B的构造函数 —>B的构造函数返回
–>A的构造函数–>A的func1–>A的func2—>A的构造函数返回–>
问题1:A的构造函数调用的是基类的func1,func2,而不锁派生类中的。因为A在构造的时候,B的对象还没构造完成,所以还不能动态绑定。所以A的构造函数结束后,A类对象的i值为11,B对象的i的值为0.
问题2:getValue返回谁的i? 应该是返回基类的i,因为getvalue不是虚函数,不动态绑定。

来看看调试步骤:
在B类中,有
(gdb) p &i
$2 = (int *) 0x804a010
(gdb) p i
$3 = 0
在A类构造函数完成后
(gdb) p &i
$5 = (int *) 0x804a00c
(gdb) p i
$6 = 11

可以看出,A,B类使用的是不同的i。

#include <iostream>
using namespace std;

class A
{
public:
    A(int j):i(j)
    {
        fun1();           //在构造函数中调用了虚函数
    }
    ~A()
    {
    }
    void fun1()
       {
           i *= 10;
           fun2();
       }
    virtual int getValue(){
    	return i;
    }
protected:
    virtual void fun2()
    {
        i++;
    }
private:
    int i;
};

class B:public A
{
public:
    B(int j):A(j)
    {
    }
    virtual ~B()
    {
    }
    virtual int getValue(){
    	return i;
    }
    void fun1()
      {
          i *= 100;
          fun2();
      }
protected:
    void fun2()
    {
        i += 2;
    }
private:
    int i;
};
int main()
{
     A* p = new B(1);
     cout<<p->getValue()<<endl;
     delete p;
     return 0;
};

这样的结果则是0。
可以参考《effective c++》

所以不要在构造函数中调用虚函数,他不会多态的。 要区分基类还是派生类。

广告位

发表评论

你必须 登陆 方可发表评论.