Explicitly constructor and virtual function call during the object lifetime

这一生的挚爱 提交于 2019-12-25 02:41:12

问题


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?


回答1:


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?




回答2:


The line...

C::C();

is outputting...

B

because foo() is being called from within B's constructor so it'll use B's version of foo().

Any time C's constructor is called, C::C() calls A's constructor which calls B's constructor in which foo() is called so B's version of foo() is used, and then C's constructor body (which you left empty) is finally called.


Let's ignore the fact that calling C::C() from main() like that doesn't conform to C++ standards. You seem to be misinterpreting part of Section 12.7/4:

...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

The call to foo is in B so the

...constructor's class...

is B and therefore

...not one overriding it in a more-derived class.

(which would be C).

You also mention "In an explicit constructor call C has already fully-contructed." The line...

C c; 

will not change the behavior mentioned in Section 12.7/4. foo() is still called B's constructor and therefore

...the function called is the final overrider in the construtor's or destructor's class.



来源:https://stackoverflow.com/questions/25541010/explicitly-constructor-and-virtual-function-call-during-the-object-lifetime

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!