C++中的指针、多态性和分段错误

Pointers, polymorphism and segmentation fault in C++

本文关键字:分段 错误 多态性 指针 C++      更新时间:2023-10-16

我有一个Parent类,它有许多子类。Parent类中的每个函数都是纯的,即没有函数的父实现,但子函数有自己的实现。不需要在那里发布代码——标准的东西。

我不希望人们从任何地方创建父类的直接实例化。我通过让虚拟函数是纯的来防止这种情况的发生,所以这很好。

我的问题是:根据用户的输入(字符串(,我想实例化一个子级。我只知道在运行时是哪一个。我(不正确?(的想法是,以下代码编译良好,工作良好,直到我将代码放入函数并返回父函数。

所以这是有效的:

Parent* parent;
if(user_input == "A") {
    Child1 child1;
    parent = &child1;
}
else if(user_input == "B") {
    Child2 child2;
    parent = &child2;
}

但这不起作用:

Parent* foo(string user_input) {
    Parent* parent;
    if(user_input == "A") {
        Child1 child1;
        parent = &child1;
    }
    else if(user_input == "B") {
        Child2 child2;
        parent = &child2;
    }
   return parent;
}

当我说它不起作用时,我的意思是,它编译了,但当我这样做时,我得到了一个分段错误:

Parent* parent = foo(user_input);
parent->some_child_function(); // segmentation error here

我确信这是一个关于我没有完全理解指针的愚蠢/简单的问题???在读了所有关于他们的书/文章之后,我仍然不知道我做错了什么。。。。这可能是单线修复?

谢谢:(。

您遇到未定义的行为:

Parent* parent;
if(user_input == "A") {
    Child1 child1; // stack-allocated object
    parent = &child1;
} //child1 is destroyed at this point, the pointer is dangling now

您必须使用new(最好使用智能指针(:

Parent* parent = 0;
if(user_input == "A") {
   parent = new Child1();
} else if(user_input == "B") {
   parent = new Child2();
}

在开始时将指针设置为null也是一个好主意,这样在代码中出现错误并且指针未初始化的情况下,就不会有带有垃圾值的指针。

尝试这个

Parent* foo(string user_input) {
    Parent* parent;
    if(user_input == "A") {
        Child1 *child1 = new Child1();
        parent = child1;
    }
    else if(user_input == "B") {
        Child2 *child2 = new Child2();
        parent = child2;
    }
   return parent;
}

基本上,在您的版本中,对象是在堆栈上创建的,当您的方法返回时,它会被清除。使用new可以确保对象是在堆上创建的,因此它会一直保留到删除为止。

但是方法的调用方需要确保他们delete对象,否则就会发生内存泄漏。

对于生产代码,使用一些类似boost的库更合适。

其他一些示例的略短版本。。。完全去掉Parent指针,并使用new分配变量。以后别忘了用delete销毁它。

Parent* foo(string user_input)
{
    if(user_input == "A") {
        return new Child1();
    }
    else if(user_input == "B") {
        return new Child2();
    }
   return NULL;
}

您必须使用运算符new在堆上分配实现类的实例。您还想了解工厂方法模式

在函数中,parent是指向本地对象的指针,一旦程序离开函数范围,该对象就会被销毁。尝试在堆中构建对象,比如parent = new child1;,使用后不要忘记delete parent

您应该研究这个解决方案的Factory模式。使用这种模式将允许任何创建不同父对象的用户只担心工厂的界面。它还可以让你更容易地添加不同的类型。使用这种模式可能看起来是一个额外的步骤,但它为您的项目添加了一个很好的抽象层,并为以后添加内容提供了更多的灵活性

class ParentFactory
{
    public:
          Parent* foo(const std::string &user_input) 
          {
              if(user_input == "A")
                  return new Child1;
              if(user_input == "B")
                  return new Child2;
              return 0;
          }
};