【发布时间】:2023-04-04 11:36:01
【问题描述】:
我正在为我当前的考试做准备,并且在其中一个问题中我得到了这个代码:
#include <iostream>
using namespace std;
struct A
{
A() : m_a(17) { cout << "A_default" << endl; }
int m_a;
};
struct B1 : A
{
B1() : m_b(1) { cout << "B1_default" << endl; }
B1(const A& a)
{
cout << "B1_constructor_with_a_parameter_A" << endl;
m_b = a.m_a + 1;
}
int m_b;
};
struct B2 : A
{
B2() : m_b(1) { cout << "B2_default" << endl; }
B2(const B1& b1)
{
cout << "B2_constructor_with_a_parameter_B1" << endl;
m_b = b1.m_b + 100;
}
int m_b;
};
int main()
{
A a1;
B1 b1;
B2 b2 = b1;
A a2 = b2;
B1 b3 = b1;
B1 b4 = b2;
return 0;
}
此代码打印:
A_default
A_default
B1_default
A_default
B2_constructor_with_a_parameter_B1
A_default
B1_constructor_with_a_parameter_A
任务是将每个打印行与 main 中相应的代码行进行匹配。除了最后打印的一行B1_constructor_with_a_parameter_A,我已经把它们都弄对了。答案纸上说这条打印线来自main() 中的B1 b4 = b2; 行,但没有解释为什么会发生这种情况。
所以我的问题很简单。 当B1 b4 = b2; 与struct B1 中的任何构造函数模式都不匹配时,为什么B1 b4 = b2; 会打印出B1_constructor_with_a_parameter_A? 这里是否发生了某种奇怪的对象切片或隐式转换?这是我最好的猜测。我有点困惑。
如果确实发生了对象切片或隐式转换。为什么B1 b3 = b1; 行不打印任何内容?我看不出B1 b3 = b1; 和B1 b4 = b2; 之间没有区别,只是b2 是B2 类型,而b1 是B1 类型。因为它们都继承A,所以不应该应用相同的规则吗?我很困惑。
【问题讨论】:
-
@t.niese 那为什么
B1 b3 = b1;不打印任何东西?B1 b4 = b2;和B1 b3 = b1;之间似乎没有区别,只是 b2 属于 B2 类型,而 b1 属于 B1 类型。不应该适用相同的规则吗? -
这里使用的命名约定是垃圾。将 B1 重命名为 B,将 B2 重命名为 C,然后将 B 类型的变量重命名为 b,将 C 类型的变量重命名为 c。这清楚地表明了表达式中使用的类型,而不是让它成为愚蠢的猎鹅。
-
@Yakk-AdamNevraumont 所说的非常真实。我不得不多次阅读以确保我是正确的。如果您想理解代码,如果您使用不会混淆的正确命名,您会更容易。
标签: c++ constructor instantiation implicit-conversion object-slicing