我有以下代码,这是我以前在另一个项目中遇到的一个问题的简化,表现出奇怪的行为。
class A
{
public:
A()
: x(12) {}
private:
int x;
};
class Base
{
public:
Base(A& a)
: a(a) {}
protected:
A a;
};
int main()
{
A a{};
class Derived : public Base
{
public:
Derived()
: Base(a) {}
};
Derived d{};
return 0;
}
该代码成功编译。假定此代码在名为
mre.cpp
的文件中,我使用GCC 9.2通过以下命令对其进行了编译:g++ -g mre.cpp -o mre
乍一看,人们可能会期望一切都如预期。值得注意的是,忽略访问修饰符,
d.a.x
应该等于12
。作为确认,让我们跳入GDB并在return 0
所在的行处设置一个断点。首先让我们看看
a
。我们可以这样运行:(gdb) p a
$2 = {x = 12}
我们可以合理地期望
d.a.x
等于12
。不幸的是,当我们执行:(gdb) p d
$1 = {<Base> = {a = {x = 32767}}, <No data fields>}
立即清楚不是这种情况。请注意,
d.a.x
的值为32767
。为什么会这样呢?这是不确定的行为吗?
另外,在我的项目中,上述问题已通过上面的代码简化了,该项目的
d
(system
)等效项显示了项目中与"Cannot access memory"
(d.a
)等效的项目中STL容器元素的部分的system.componentManager
。 。这是GDB中的样子:(gdb) p system.componentManager
$3 = (planes::engine::ecs::ComponentManager &) @0x7fffffffcb40: {
typeNameToArrayMap = std::unordered_map with 2 elements<error reading variable: Cannot access memory at address 0x7fff3f800000>,
typeNameToIndexMap = std::unordered_map with 140734258741248 elements<error reading variable: Cannot access memory at address 0x1>, nextComponentTypeIndex = 2}
实际上,可以通过将
Derived
构造函数更改为来解决此问题。Derived(A& a)
: Base(a) {}
并在
a
初始化期间将d
作为构造函数参数传递,即Derived d{a}
。
最佳答案
a
类构造函数中的Derived
Derived()
: Base(a) {}
是基类中的成员变量
a
,而不是main
中的局部变量。当您将
Derived
类构造函数更改为Derived( A& a )
: Base(a) {}
这个新的函数参数
a
隐藏了成员变量。要进一步了解发生了什么,请尝试重命名本地变量
a
。例如
A x;
Derived()
: Base(x) {}
这应该告诉您,不允许在封闭函数中引用局部变量。
关于c++ - 从派生类将非构造函数参数变量传递给基类构造函数会导致奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60835314/