了解虚拟基类和构造函数调用

发布于 2024-11-16 16:51:18 字数 711 浏览 3 评论 0原文

我对虚拟基类的工作原理有点困惑。特别是,我想知道如何调用基类的构造函数。我写了一个例子来理解它:

#include <cstdio>
#include <string>
using std::string;

struct A{
    string s;
    A() {}
    A(string t): s(t) {}
};

struct B: virtual public A{
    B(): A("B"){}
};

struct C: virtual public A {};

struct D: public B, public C {};

struct E: public C, public B {};

struct F: public B {};

int main(){
    D d;
    printf("\"%s\"\n",d.s.c_str());
    E e;
    printf("\"%s\"\n",e.s.c_str());
    F f;
    printf("\"%s\"\n",f.s.c_str());
    B b;
    printf("\"%s\"\n",b.s.c_str());
}

哪些输出

""
""
""
"B"

我不确定在前两种情况下会发生什么,但对于第三种情况,至少我期望输出为“B”。所以现在我很困惑。理解 A 的构造函数如何被调用的规则是什么?

I'm a bit confused about how virtual base classes work. In particular, I was wondering how the constructor of the base class gets called. I wrote an example to understand it:

#include <cstdio>
#include <string>
using std::string;

struct A{
    string s;
    A() {}
    A(string t): s(t) {}
};

struct B: virtual public A{
    B(): A("B"){}
};

struct C: virtual public A {};

struct D: public B, public C {};

struct E: public C, public B {};

struct F: public B {};

int main(){
    D d;
    printf("\"%s\"\n",d.s.c_str());
    E e;
    printf("\"%s\"\n",e.s.c_str());
    F f;
    printf("\"%s\"\n",f.s.c_str());
    B b;
    printf("\"%s\"\n",b.s.c_str());
}

Which outputs

""
""
""
"B"

I wasn't sure what would happen in the first two cases, but for the third one at least I was expecting the output to be "B". So now I'm just confused. What are the rules for understanding how the constructor of A gets called?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼眸 2024-11-23 16:51:18

始终只有一个构造函数调用,并且始终是您实例化的实际具体类。 有责任为每个派生类赋予一个构造函数,该构造函数在必要时调用基类的构造函数,就像您在 B 的构造函数中所做的那样。

更新:很抱歉错过了您的要点!感谢伊尔贾恩。

但是,您的 B 实际上继承了 A。根据标准(FIDS 中的 10.1.4),“对于指定为虚拟的每个不同基类,最派生的对象应包含该类型的单个基类子对象”。在您的情况下,这意味着在构造基类时,您的类 F 立即调用 A 的默认构造函数,而不是 B 的默认构造函数。

There is always just one constructor call, and always of the actual, concrete class that you instantiate. It is your responsibility to endow each derived class with a constructor which calls the base classes' constructors if and as necessary, as you did in B's constructor.

Update: Sorry for missing your main point! Thanks to ildjarn.

However, your B inherits virtually from A. According to the standard (10.1.4 in the FIDS), "for each distinct baseclass that is specified virtual, the most derived object shall contain a single base class subobject of that type". In your case this means that when constructing the base, your class F immediately calls A's default constructor, not B's.

_蜘蛛 2024-11-23 16:51:18

虚拟基类总是由最派生的类构造。

Virtual base classes are always constructed by the most derived class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文