c++ - 从派生类将非构造函数参数变量传递给基类构造函数会导致奇怪的行为

标签 c++

我有以下代码,这是我以前在另一个项目中遇到的一个问题的简化,表现出奇怪的行为。

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/

相关文章:

c++ - 如何在制定目标后设置变量?

c++ - 继承中的函数定义

c++ - 绘图功能的表现

c++ - <eof> 附近的 lua 函数参数

c++ - 将一个字节组合成 long long

c++ - 嵌套的 openmp 循环

c++ - Boost 库和 Visual Studio 2013

c++ - 使用gcc插件修改变量声明的顺序

C++ 继承具有不同默认参数值的函数

c++ - 一种下载所有必需的 kde 依赖项以开始进行 kde 编程的方法?