在非构造的“对象”上调用非虚拟成员函数是不是定义明确? [复制]
Posted
技术标签:
【中文标题】在非构造的“对象”上调用非虚拟成员函数是不是定义明确? [复制]【英文标题】:Is calling a nonvirtual member function on a non-constructed "object" well-defined? [duplicate]在非构造的“对象”上调用非虚拟成员函数是否定义明确? [复制] 【发布时间】:2014-01-16 18:27:22 【问题描述】:在构造函数内部,允许调用非虚成员函数。
从这个事实是否可以得出以下代码是明确定义的?
struct A
void foo std::cout << "Hi there! My address is: " << this;
;
A * a = nullptr;
a->foo ();
回答?
借助 cmets 中给出的一些链接,以及链接页面中给出的链接,我现在认为可以找到答案,例如在
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3035.pdf
§3.8 标准。第 5 页。 66:
“在对象的生命周期开始之前,但在分配对象将占用的存储空间之后...... [t]程序具有未定义的行为 如果 [...] 指针用于访问非静态数据成员或调用对象的非静态成员函数"
如果根本没有分配存储,那么调用成员函数应该更加未定义。
我想这里解释了为什么将其设为 undefined 是个好主意的一个重要原因:https://***.com/a/3257755/1419315
【问题讨论】:
***.com/questions/2533476/… 【参考方案1】:该代码是未定义的行为。
注意在构造函数内部你也可以调用虚成员函数。
有点棘手的部分是在构造函数代码开始之前的成员初始化期间调用虚拟成员函数。仍然有效,但不明显会发生什么(关键是在构造函数代码开始之前,对象还没有被视为其类的实例,并且虚拟成员函数被分派到基类)。
如果您在成员初始化列表中使用 this
,某些编译器会发出警告,这正是因为 this
指针在该点会表现异常(只有在构造函数启动后才会开始正常运行)。
代码显然有效,因为大多数编译器使用 VMT 方法进行方法分派,但调用非虚拟方法不需要 VMT,因此如果方法代码不以任何方式取消引用this
然后事情似乎“起作用”。然而,代码似乎在一个实现(或者甚至在每个实现中)都可以工作的事实仍然不能使它成为合法的 C++ 代码。
【讨论】:
据我所知,您不应该在 ctor 内部调用虚方法。 @Manu343726 只是因为它可能不会做你想做的事。如果它做你想做的事,它没有错,它在标准 C++ 中是有效的。 @hvd 哦,因为如果你有一个类层次结构,你实例化一个派生类的对象(哪个构造函数首先调用基类构造函数)并且在基类ctor中你调用一个虚函数? @hvd 我完全不明白的是:对象的 vptr 不是在执行任何 ctor 和基础 ctor 之前初始化的吗?如果这是真的,那么基本 ctor 中的虚拟调用就没有问题了。 @Manu343726 你太担心实施细节了,IMO。从概念上讲,它更简单。给定struct S2 : S
,构造S2
首先创建一个S
子对象,然后才创建完整的S2
。在S
子对象的构造过程中,没有S2
对象,如果没有S2
对象,就不能调用S2
的方法,所以虚方法调用除了@987654332之外别无他法@的实现。如果这就是你想要调用的,那么这样做没有错。但是,是的,您对如何实现对象构造的想法是它在其他一些环境/语言中的工作方式。以上是关于在非构造的“对象”上调用非虚拟成员函数是不是定义明确? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
Zend\Mail 标头:在非对象上调用成员函数 setType()
致命错误:在非对象上调用成员函数 getLoginUrl()