2015-04-05 17 views
-2

我得到這個代碼:屬性值添加到一個向下鑄結構導致分段錯誤

#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->name2 = "bajs";行導致(隨機)分段錯誤。我只是想知道如何糾正這個不會導致分段錯誤。我仍然想要調用createNode()來創建基節點並設置所有屬性成員。在c++可行嗎?

+0

你爲什麼要混合模板和繼承這種方式?如果'createNode'是一個模板,那麼你不應該在其中創建一個'new Base'。如果你想繼承刪除模板並讓方法返回'Base' – ZivS 2015-04-05 07:58:07

+0

很難說明爲什麼派生類有'string name2;'。另外我認爲''createNode''應該在'Base * node = new Base(name)'語句中使用'T'而不是'Base''' – VolAnd 2015-04-05 07:59:04

+0

您不能僅僅指向一個基礎對象來指向派生類型,並期望它工作。指向的對象仍然是一個「基礎」。它沒有'name2'成員。 – juanchopanza 2015-04-05 08:03:36

回答

1

也許,我不明白你的程序的想法,但我認爲,它必須是這樣的:

#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; 
} 
+0

我希望'createNode()'創建基類,然後向其中添加彈出窗口,因爲我希望我的程序是乾的。基類包含許多可以被任何派生類繼承的道具。 – einstein 2015-04-05 08:31:04

+0

@einstein @einstein C++有一個類型系統,一旦創建了一個對象,它就不能改變類型或添加新的字段或任何東西 – 2015-04-05 08:32:52

+0

@einstein:但是在你的代碼中,你創建基類的元素,並試圖使用不存在的字段基類。 – VolAnd 2015-04-05 08:33:24

2

這段代碼:

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。由於Derived需要比Base更多的空間,所以當您使用name2時,您正在覆蓋createNode中創建的對象之外的內容。 name2也沒有被構建,這意味着該任務很可能使用隨機垃圾值,這本身很可能會導致崩潰。

您將需要重新排列代碼,以便它首先創建正確的對象,並且如果要使用構造函數,則需要具有用於獲取指定對象的Derived的構造函數。 [還有其他方法可以實現這一點,但通常不是你想在這裏]

+0

感謝您的解釋。我將在未來使用更多的najser詞。但是,無論如何,我可以用一個函數創建基類,該函數設置基本屬性,然後將屬性添加到此對象?我的基類包含很多可以繼承的屬性。 – einstein 2015-04-05 08:22:23

+0

@einstein也許你正在尋找裝飾模式? http://stackoverflow.com/questions/2988066/decorator-pattern-in-c – PaulMcKenzie 2015-04-05 08:31:45

+0

簡單地說,沒有。有多種方式可以將其他事物「添加」到其他東西 - 裝飾器模式是一種,在類中有一個容器類型('vector','map'或類似的)是另一種。哪一個最合適取決於你實際想要達到的目標。 – 2015-04-05 12:09:25