Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+中的指针、多态性和分段错误+;_C++_Segmentation Fault - Fatal编程技术网

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

C++ C+中的指针、多态性和分段错误+;,c++,segmentation-fault,C++,Segmentation Fault,我有一个有很多孩子的家长班。父类中的每个函数都是纯函数,即没有函数的父实现,但子类有自己的实现。不需要在那里张贴代码-标准的东西 我不希望人们在任何地方创建父类的直接实例化。我通过让虚拟函数是纯函数来防止这种情况,所以这很好 我的问题是:根据用户的输入(字符串),我想实例化一个子项。我只知道在运行时是哪一个。我(不正确?)的想法是,在我将代码放入函数并返回父函数之前,编译良好,工作正常 所以这是可行的: Parent* parent; if(user_input == "A") { Ch

我有一个有很多孩子的家长班。父类中的每个函数都是纯函数,即没有函数的父实现,但子类有自己的实现。不需要在那里张贴代码-标准的东西

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

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

所以这是可行的:

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
(最好使用智能指针):


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

在函数
中,parent
是指向本地对象的指针,一旦程序离开功能范围,它就会被销毁。尝试在堆中构造对象,如
parent=newchild1删除父级。

必须在堆上分配实现类的实例。您还需要调查。

试试这个

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
可确保在堆上创建对象,因此在删除之前,对象将一直保留在堆中

但是方法的调用者需要确保他们
删除
对象,否则会导致内存泄漏


对于生产代码,使用boost之类的库更合适

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

Parent* foo(string user_input)
{
    if(user_input == "A") {
        return new Child1();
    }
    else if(user_input == "B") {
        return new Child2();
    }
   return NULL;
}
您应该研究此解决方案的解决方案。使用此模式将允许创建不同父对象的任何用户只关心工厂的接口。它还可以让您更轻松地添加不同的类型。使用此模式可能看起来是一个额外的步骤,但它为您的项目添加了一个很好的抽象层,并且为以后添加内容增加了一点灵活性

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;
          }
};

你知道你不需要那些
()
调用新的
调用,对吗?@Nikolai-根据和,是的,你确实需要那些
()
调用新的调用。嗯,不。正确的默认初始化是类的责任,而不是调用方的责任。或者我认为。。。
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;
          }
};