簡體   English   中英

C++ 中的指針、多態性和分段錯誤

[英]Pointers, polymorphism and segmentation fault in C++

我有一個父母 class 有很多孩子。 父 class 中的每個 function 都是純的,即沒有函數的父實現,但子有自己的實現。 無需在那里發布代碼 - 標准的東西。

我不希望人們從任何地方創建父 class 的直接實例化。 我通過讓虛函數是純的來防止這種情況發生,這很好。

我的問題:根據用戶的輸入(字符串),我想實例化其中一個孩子。 我只知道在運行時是哪一個。 我的(不正確?)想法如下,它編譯得很好並且工作正常,直到我將代碼放入 function 並返回父級。

所以這有效:

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

基本上在您的版本中,object 是在堆棧上創建的,當您的方法返回時,它會被清除。 使用new可確保在堆上創建 object,因此它會一直保留在那里直到被刪除。

但是你的方法的調用者需要確保他們delete了對象,否則你有 memory 泄漏。

對於使用諸如 boost 之類的庫的生產代碼更合適。

其他一些示例的略短版本...完全擺脫 Parent 指針,並使用 new 分配您的變量。 不要忘記稍后使用刪除將其銷毀。

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

您必須使用operator new在堆上分配實現類的實例。 您還想研究Factory Method Pattern

在你的函數中, parent是一個指向本地 object 的指針,一旦程序離開 function scope,它就會被銷毀。 嘗試在堆中構造 object,如parent = new child1; 並且不要忘記在使用后delete parent級。

您應該研究此解決方案的工廠模式 使用這種模式將允許任何創建不同父對象的用戶只擔心工廠的界面。 它還將允許您在以后更輕松地添加不同的類型。 使用這種模式可能看起來像是一個額外的額外步驟,但它為您的項目添加了一個很好的抽象層,並為以后添加東西提供了更多的靈活性。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM