C++ 是否有一个超类';在C+中未调用s构造函数+;?

C++ 是否有一个超类';在C+中未调用s构造函数+;?,c++,inheritance,constructor,C++,Inheritance,Constructor,这个问题让我在一次采访中被问到了。如果B是A的子类。当构造B时,是否有一段时间a的构造函数没有被调用 编辑:我告诉面试官我想不出这种情况,因为我认为只有在构造子类之前正确地构造一个超类才有意义。一个可能的例子是当a和B都没有用户声明的构造函数,并且B的一个实例正在创建时值已初始化 A和B都隐式声明了构造函数,在初始化过程中不会使用这些构造函数 类似地,如果A没有用户声明的构造函数,但出现在B的构造函数的成员初始值设定项列表中,但初始值设定项为空,则当使用B的构造函数时,将初始化A的值。同样,由于

这个问题让我在一次采访中被问到了。如果B是A的子类。当构造B时,是否有一段时间a的构造函数没有被调用


编辑:我告诉面试官我想不出这种情况,因为我认为只有在构造子类之前正确地构造一个超类才有意义。

一个可能的例子是当
a
B
都没有用户声明的构造函数,并且
B
的一个实例正在创建时值已初始化

A
B
都隐式声明了构造函数,在初始化过程中不会使用这些构造函数


类似地,如果
A
没有用户声明的构造函数,但出现在
B
的构造函数的成员初始值设定项列表中,但初始值设定项为空,则当使用
B
的构造函数时,将初始化
A
的值。同样,由于
A
没有用户声明的构造函数,因此值初始化不使用构造函数。

在A完全构造之前,B的构造甚至不能开始,所以答案是

我想您可以在为B的初始化列表中的a生成非默认构造函数的参数时抛出异常

struct B {...};
struct D1 : virtual B {...};
struct D2 : virtual B {...};
struct Child : D1, D2 {...};
您可以在下面看到,从未调用的构造函数,因为在为其生成参数时发生异常

#include <iostream>

using namespace std;

int f()
{
    throw "something"; // Never throw a string, just an example
}


class A
{
public:
    A(int x) { cout << "Constructor for A called\n"; }
};


class B : public A
{
public:
    B() : A(f()) {}
};


int main()
{
    try 
    {
        B b;
    }
    catch (const char* ex) 
    {
        cout << "Exception: " << ex << endl;
    }
}
#包括
使用名称空间std;
int f()
{
抛出“某物”;//永远不要抛出字符串,只是一个例子
}
甲级
{
公众:

A(int x){cout如果B在A之前构造了第二个超类,那么A的构造函数将有一段时间没有被调用,尽管它将被调用。

虚拟继承

struct B {...};
struct D1 : virtual B {...};
struct D2 : virtual B {...};
struct Child : D1, D2 {...};


通常构造函数
B()< /代码>应该被调用两次,但它只会被调用一次。

只是出于好奇,你的答案是什么?我想知道什么地方仍然使用C++的边缘案例琐事作为面试问题的一种形式。在什么情况下,编码是很重要的,知道答案是否正确。“Andy Finkenstadt,是MIG。”对于那些自称为“专家”的人来说,这是有用的马克,我编辑了这个问题。如果没有办法,那么我想面试官可能在看我的思维过程。如果这是与思维过程有关的事情,我有一些有趣的答案。检查下面。从问题的上下文来看,我会认为
A
有一个构造函数,但是一个很好的漏洞。@Mark:a有一个构造函数。它没有用户定义的构造函数:-)在最后一个例子(你的最后一段)中,我没有意识到这一点
A
如果在A
B
构造函数的初始值设定项列表中存在空的初始值设定项,则将严格进行值初始化。事实上,如果有的话,我会很快假设这样的存在是一个显式的默认构造函数调用。您知道得越多…值初始化意味着什么?我猜这意味着隐式生成副本constructuctor也是构造函数,它被调用(不一定是通过
call
asm指令或其他方式调用的,但它是根据语言语义调用的)。@Ben:行为不同。在值初始化时,任何
int
成员都被设置为0。默认生成的构造函数不(必然)这样做。但B的构造也不会发生。@Unaperson:B的构造已开始(但不返回).所以问题的条件得到了满足。@JohnB:回答得很好。起初我没有注意到这一点。我认为从技术上讲,
B
的构造还没有开始;
A
的构造是一种先决条件。这仍然是一个有趣的边缘案例。@Mark ransem:“一种先决条件”它不是先决条件。它是构造过程的必要部分。如果您在程序中的任何位置使用特定构造函数(例如,初始化基/成员、初始化简单对象、在某些表达式中创建临时对象、新建表达式)你总是指所有的构造步骤,而不仅仅是执行构造函数的函数体。我猜你的意思是,B构造函数的函数体在A完全构造之前是没有输入的,这是真的。但B对象的构造肯定在第一个初始化列表表达式执行之前就开始了。所以你错了。我相信创建特定对象的第一步是创建其所有子对象,包括超级类型。最后一步是实际输入其构造函数。@Serge Dundich,标准对构造顺序有很好的规定。也许您对“构造”的定义太过宽松了-例如,不包括为对象保留内存。“可能您使用的定义太松散”不完全包括。保留内存确实不包括在内,但包括构造基类和非静态成员。执行构造函数的boby只是最后一步。对象的构造是使用placement new时发生的一切(就像纯粹的构造-没有内存分配)。这就是我要给出的示例。
B
的构造通常发生在
D1
的构造过程中,但在虚拟继承中,
B
的构造发生在
子类的构造过程中,
D1::D1
不调用其基类构造函数。我也考虑了这一点,但拒绝了它。基类构造函数仍然被调用,这满足了问题标题中的查询。从Q的文本——“当构造B时,是否有一段时间a的构造函数没有被调用?”-这有点模棱两可,因为不清楚“当构造”是否/如何对所考虑的时间范围进行限制。Wort