【问题标题】:Add property value to a down cast struct causes segmentation fault将属性值添加到向下转换结构会导致分段错误
【发布时间】:2015-04-05 07:54:07
【问题描述】:

我得到了这个代码:

#include <iostream>
#include <string>

using namespace std;

struct Base {
  Base(string name) {
    this->name = name;
  }
  string name;
};

struct Derived: Base {
  string name2;
};

template <typename T>
T createNode(string name) {
  Base* node = new Base(name);
  return static_cast<T>(node);
}

int main() {
  Derived* node = createNode<Derived*>("hej");
  node->name2 = "bajs";
  cout << node->name2;
}

node-&gt;name2 = "bajs"; 行会导致(随机)分段错误。我只是想知道如何纠正此问题以免导致分段错误。我仍然想调用createNode() 来创建基础节点并在之后设置所有属性成员。在c++可以吗?

【问题讨论】:

  • 为什么要这样混合模板和继承?如果 createNode 是一个模板,那么你不应该在其中创建一个 new Base。如果你想继承删除模板并让方法返回Base
  • 很难理解为什么派生类有string name2;。另外我认为createNode 应该在声明Base* node = new Base(name); 中使用T 而不是Base
  • 您不能只将指向基础对象的指针大小写为指向派生类型的指针并期望它能够工作。指向的对象仍然是Base。它没有name2 成员。
  • 我想重读 C++ 教科书是当务之急
  • 在节目中说“便便”真是太有趣了,太棒了,真的很成熟。

标签: c++


【解决方案1】:

这段代码:

template <typename T>
T createNode(string name) {
  Base* node = new Base(name);
  return static_cast<T>(node);
}

创建Base 类型的对象。

这个:

  Derived* node = createNode<Derived*>("hej");
  node->name2 = "najs";    // No need to use rude words, even if you think most people can't read them.

使用创建的对象作为Derived。由于DerivedBase 需要更多空间,因此当您使用name2 时,您将覆盖在createNode 中创建的对象之外的内容。 name2 也没有被构造,这意味着分配很可能使用随机垃圾值,这本身很可能导致崩溃。

您需要重新排列您的代码,以便它首先创建正确的对象,如果您想使用构造函数,您需要有一个 Derived 的构造函数来获取命名对象。 [还有其他一些方法可以实现这一点,但通常不是你想要的]

【讨论】:

  • 感谢您的解释。将来我会使用更多的 najser 词。但是无论如何我不能使用设置基本属性的函数创建基类,然后向该对象添加属性吗?我的基类包含很多可以继承的属性。
  • @einstein 也许您正在寻找装饰器模式? stackoverflow.com/questions/2988066/decorator-pattern-in-c
  • 简单地说,没有。有多种方法可以“添加”到其他事物 - 装饰器模式是一种,在类中具有容器类型(vectormap 或类似)是另一种。哪个最合适取决于您实际想要达到的目标。
【解决方案2】:

也许,我不明白你的程序的想法,但我认为,它必须是这样的:

#include <iostream>
#include <string>

using namespace std;

struct Base {
  Base(string name) {
    this->name = name;
  }
  string name;
};

struct Derived: Base {
    Derived(string name):Base(name)
    {
    }
    // string name2; // it is not needed
};

template <typename T>
T* createNode(string name) {
  T* node = new T(name);
  return node;
}

int main() {
  Derived* node = createNode<Derived>("hej");
  node->name = "bajs";
  cout << node->name;
}

【讨论】:

  • 我希望 createNode() 创建基类,然后向它添加 pops,因为我希望我的程序是 DRY。基类包含许多可以被任何派生类继承的道具。
  • @einstein C++ 有一个类型系统,一旦创建了一个对象,它就不能改变类型或添加新字段或任何东西
  • @einstein :但是在您的代码中,您创建了基类的元素并尝试使用基类中不存在的字段。
  • @VolAnd 感谢您的解释。我只是使用了您的示例并对其进行了更正以适应我的目的。
猜你喜欢
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-16
  • 2018-07-03
  • 1970-01-01
  • 1970-01-01
  • 2014-12-27
相关资源
最近更新 更多