C++在构造函数中调用成员函数,实例化子类,输出结果有些出乎意料

2017-05-03 13:25:10 +08:00
 sbabybird

试验代码如下

class CHello {
 public:
  CHello()
  {
    this.SayHello();
  }
  virtual ~CHello();
  virtual void SayHello()
  {
    printf("hello");
  }
};

class CHelloA : public CHello {
 public:
  CHelloA();
  ~CHelloA();
  void SayHello() 
  {
    printf("hello a");
  }
};

void main() 
{
  CHelloA a;
}

猜猜输出什么?

2539 次点击
所在节点    C
22 条回复
sbabybird
2017-05-03 13:26:32 +08:00
同样的思路,在 java 和 python 下输出是正常的,即子类的 SayHell 被调用。
sbabybird
2017-05-03 13:29:40 +08:00
在 vs2015 下编译的,输出显示调用的是父类的 SayHello。
nyanyh
2017-05-03 13:31:18 +08:00
vingz
2017-05-03 13:32:41 +08:00
Hello?
limhiaoing
2017-05-03 13:32:50 +08:00
这代码能编译通过?
wevsty
2017-05-03 13:34:41 +08:00
1、楼主的代码编译都过不了
this 是指针,指针类型不能用.来调用
CHelloA,~CHelloA,~CHello 都只有声明没有定义,link 的时候会 error 的
2、如果正确修改代码
那么最后应该是输出 hello 而不是 hello a
solaya
2017-05-03 13:36:15 +08:00
这代码 你跑过???去看看 effective c++
wangxn
2017-05-03 13:38:25 +08:00
不要在构造函数和析构函数中调用虚函数,不是一个常识吗?楼主真是大惊小怪啊……
vingz
2017-05-03 13:40:24 +08:00
java 下,如果 sayHello 是 private 权限,父类的函数被调用,如果是其他权限(测试了 default,protected )子类的函数被调用。
sbabybird
2017-05-03 13:43:45 +08:00
不好意思,那个点写错了,应该是 this->SayHello();我是凭记忆打的,确实在 vs 下运行过。 @solaya
wangxn
2017-05-03 13:43:52 +08:00
Python 之所以能在构造函数中调用到子类中的同名函数,原因在于 Python 压根没有虚函数这个概念,所谓调用只是 self 对象在它自己的 __dict__ 中进行名字查找而已。
sbabybird
2017-05-03 13:44:46 +08:00
@wangxn 只是想探讨一下原因,以及跟其他语言的不同
sbabybird
2017-05-03 13:45:30 +08:00
@wevsty 是的确实输出的是 hello
limhiaoing
2017-05-03 13:48:47 +08:00
@sbabybird
想探讨原因就不应该用这种标题!
wevsty
2017-05-03 13:57:23 +08:00
@sbabybird
对 C++来说 virtual 函数是在类对象里面有虚表来确定执行哪个函数的,但是继承过来的对象不修改基类中的虚表,而是附加新的。
继承并不是单纯的按照基类复制成一个新的类,这里是依赖关系所以仍然会保持基类里原有的行为,在基类中实现构造的时候就确定下来的行为是不会改变的。
sbabybird
2017-05-03 13:58:53 +08:00
@limhiaoing 抱歉了哈,确实有些随意了,感谢指正
huyan3280
2017-05-03 14:43:15 +08:00
hello
Taojun0714
2017-05-03 16:08:19 +08:00
去看《深度探索 C++对象模型》
Pyjamas
2017-05-03 16:09:15 +08:00
上面+1
geelaw
2017-05-03 16:11:36 +08:00
对象的身份(具体度)是逐渐升级的。

这也是为什么会有“调用过了纯虚函数”这种错误,在基类的构造函数里面调用纯虚函数会失败。

析构的时候对象身份逐渐降级。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/358777

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX