在对象生命周期中显式构造函数和虚函数调用 [英] Explicitly constructor and virtual function call during the object lifetime

查看:128
本文介绍了在对象生命周期中显式构造函数和虚函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们可以使用qualified-name来调用构造函数,虽然构造函数没有名称。实际上,3.4.3.2/2:


在不忽略函数名称和
nested-name-提名类C:



- 如果在C语言中查找嵌套名称说明符后指定的名称是
inject-class-name of C(Clause 9),or



[...]



考虑下面的例子:



<$ p $

p> #include< iostream>

使用std :: cout;
using std :: endl;

struct A
{
virtual void foo()
{
cout< A<< endl;
}

A(){}
};

struct B:A
{
virtual void foo()
{
cout< B< endl;
}

B()
{
foo();
}
};

struct C:B
{
virtual void foo()
{
cout< C< endl;
}

C():B(){}
};

C c;

int main()
{
c.foo();
C :: C(); // Prints B
}

演示



C :: C()打印B.但不清楚。第12.7节/ 4说:


当一个虚函数直接或间接从
构造函数或析构函数调用时,包括在构建期间或
销毁类的非静态数据成员,以及调用应用的对象
>是对象(称为x)正在构建中或
销毁,调用的函数是
构造函数或析构函数类中的最终覆盖函数,没有一个覆盖它在
更多派生类


在显式构造函数调用 c 已经完全构成。所以我引用的规则不能用来解释这种行为。它是UB吗?

解决方案


我们可以使用qualified-name来调用一个构造函数,没有名称。


您的前提是完全错误的。在您引用的非常相同的段落(§3.4.3.1[class.qual] / p2):


这样的构造函数名称只能在命名构造函数的
声明的 declarator-id 中或在 using-declaration 中使用。


C :: C(); 一个声明命名一个构造函数?不是。使用声明吗?很明显不是。



它的形状不好。 Clang似乎认为它命名的类型,而不是,由于某种原因 - 可能是一个错误(其处理 inject-class-names 在其他方面也是错误的)。






我也不知道你是如何得出结论: C :: C(); - 顺便说一下,如果你考虑 C :: C 命名类型 - 可能会受到 c



对一个对象的一个​​假设的显式构造函数调用必须看起来像 cC :: C(); ,因为构造函数是一个非静态成员函数。并且没有任何意义允许你在已经构造的对象上调用构造函数 - 这是什么意思?


We can call a constructor using qualified-name, although the constructor doesn't have a name. Indeed 3.4.3.2/2:

In a lookup in which function names are not ignored and the nested-name-specifier nominates a class C:

— if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (Clause 9), or

[...]

the name is instead considered to name the constructor of class C.

Consider the following example:

#include <iostream>

using std::cout;
using std::endl;

struct A
{
    virtual void foo()
    {
        cout << "A" << endl;
    }

    A(){ }
};

struct B : A
{
    virtual void foo()
    {
        cout << "B" << endl;
    }

    B()
    {
        foo();
    }  
};

struct C : B
{
    virtual void foo()
    {
        cout << "C" << endl;
    }

    C() : B(){ }      
};

C c;

int main()
{
    c.foo();
    C::C(); // Prints B
}

demo

The line C::C() prints B. But it's unclear. Section 12.7/4 says:

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

In an explicit constructor call c has already fully-contructed. So the rule I cited cannot be used to explain such behavior. Is it UB at all? Could you explain it?

解决方案

We can call a constructor using qualified-name, although the constructor doesn't have a name.

Your premise is completely wrong. In the very same paragraph you cited (§3.4.3.1 [class.qual]/p2):

Such a constructor name shall be used only in the declarator-id of a declaration that names a constructor or in a using-declaration.

Is C::C(); a declaration that names a constructor? No. Is it a using-declaration? Obviously not.

It's ill-formed. Clang seems to consider it to name the type instead, for some reason - probably a bug (its handling of injected-class-names is also buggy in other respects).


I also have no idea how you came to the conclusion that the behavior of C::C(); - which, incidentally, only makes any sense if you consider C::C to name the type - could possibly be affected by the state of c, which appears nowhere in the expression nor in any of the relevant functions.

A hypothetical explicit constructor call on an object would have to look like c.C::C();, because the constructor is a non-static member function. And it makes no sense whatsoever to permit you to call a constructor on an already-constructed object - what does that even mean?

这篇关于在对象生命周期中显式构造函数和虚函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆