2013-06-26 59 views
1

我目前正在使用C++進行大學項目,我的一項任務是使用繼承和多態性構建社交網絡。目前我有一個在地圖Multimap上使用的節點類(兩者都是手動創建的,並未從標準中使用)。節點可以在那裏我用它容納兩個變量(關鍵數據爲例),並且在第一個變量可以是一個指針或字符串(他們讓我們用的std :: string)。如何使用繼承作爲參數的std ::字符串?

時遇到的問題是,當我從「根」級(對象)繼承,並使用「對象」作爲「鑰匙」數據類型,我無法通過與創建的串std as參數指向其構造函數,因爲它不從我的Object類繼承。一種解決方案是實現我自己的字符串類並使其從Object繼承,但我正在尋找其他解決方法。

如果上述邏輯有任何問題,請告訴我,因爲我剛剛開始使用C++。

EDIT 1(我的節點中的某些代碼):

class TempNode 
{ 
    private: 
    TempNode* next; 
Key key; 
T value; 
public: 
TempNode(); 
explicit TempNode(const Key thisKey, const T thisValue, TempNode* thisNext = NULL) 
: key(thisKey) 
, value(thisValue) 
, next(thisNext) 
{ 
} 
inline Key getKey() { return key; } 
inline T getValue() { return value; } 
inline TempNode* getNext() { return next; } 
inline void setNext(TempNode* thisNext) { next = thisNext; } 
}; 

字符串或人類型目前僅在關鍵使用,但這是另一種實現方式使用模板(其中正常工作),但我的老師現在要求我們將繼承應用到整個項目中(我想我已經習慣了)。

+2

請使用一些示例代碼來顯示您當前正在嘗試的內容,即使您知道這是錯誤的。 – aschepler

+0

你可以將'std :: string'包裝在派生自Object的某個類中,因此這是可能的。 – dyp

+0

@aschepler我添加了我的節點類和一些更多的解釋。 –

回答

1

爲了實現這個使用繼承,你認爲Key如在地圖/ multimap中實施的關鍵專門的數據類型。 Key繼承自Object,但它可以提供其自己的特定於鍵的功能,例如–,例如–函數repr(),其生成由地圖用於某些地圖特定操作的表示(可以作爲散列或排序的基礎管他呢)。

地圖/多重映射必須以這樣的方式使得Key對象存儲作爲指針被使用(或std::unique_ptr,或std::shared_ptr,或任何爲宜),但不作爲Key對象的副本。

因此,我們有:

struct Object 
{ 
    virtual ~Object() 
    { } 
}; 

/* Key class. Pointers of this type are inserted 
    into the map. */  
class Key : public Object 
{ 
public: 
    /* Must be supported by all keys: */ 
    virtual std::string repr() const = 0; 
}; 

我們還假設有Person對象的單獨定義:

struct Person : Object 
{ 
    Person(const std::string &name) 
    : name_(name) 
    { } 

    std::string name_; 
}; 

根據您的具體要求,也有Key兩種形式:一種是代表字符串並且必須使用一個字符串進行初始化,另一個代表人員,並且必須由人員指針初始化(我將假設人員密鑰實際上並不是自己的這些指針,因此只要人員密鑰存在,您就需要確保指向的人員對象保持活動狀態)。

我們通過專業Key成兩個派生類,一個PersonKey和實施這樣的StringKey

class PersonKey : public Key 
{ 
public: 
    PersonKey(Person *person_ptr) 
    : Key() , person_ptr_(person_ptr) 
    { } 

    virtual std::string repr() const 
    { 
    if (person_ptr_ != 0) 
     return std::string("Person/") + person_ptr_->name_; 
    else 
     return "<NUL>"; 
    } 

private: 
    Person *person_ptr_; 
}; 

class StringKey : public Key 
{ 
public: 
    StringKey(const std::string &str) 
    : Key() , str_(str) 
    { } 

    virtual std::string repr() const 
    { 
    return str_; 
    } 

private: 
    std::string str_; 
}; 

當您插入到地圖/ multimap中,你產生Key對象(你代表爲Key*Key&std::unique_ptr<Key>)。當你想插入一個字符串,你生成它們作爲StringKey對象,當你想插入他們作爲人的三分球,你用PersonKey –但你插入鑰匙的數據類型將不會反映專業化。

這裏是一個一般Key對象的一個​​例子(作爲std::unique_ptr<Key>實現,但可以只使用Key*如果不怕內存泄漏的):

int main() 
{ 
    /* General key object: */ 
    std::unique_ptr<Key> mykey; 

    /* Now it points to a string-key, initialized using 
    a string, as required: */ 
    mykey.reset(new StringKey("hello")); 
    std::cout << "repr(mykey) == \"" 
      << mykey->repr() 
      << '"' 
      << std::endl; 

    /* Now the same key object is made to refer to 
    a person object: */ 
    Person person("me"); 
    mykey.reset(new PersonKey(&person)); 
    std::cout << "repr(mykey) == \"" 
      << mykey->repr() 
      << '"' 
      << std::endl; 

    return 0; 
} 

爲上述代碼必要的標頭是:

#include <iostream> 
#include <memory> 
#include <string> 

(但memory只需要爲我用的std::unique_ptr,這是不實際需要來解決你的問題。)

+0

謝謝!這似乎是一個更好的實現方法。 –

0

我認爲你真正想要的是模板。您使用「根對象」的解決方案不能像標準對象和外部庫一樣工作,但也不能使用容器的基元(例如person id(int)作爲關鍵字,Person類作爲關鍵字值)。

有了模板,你可以說你將在編譯時使用什麼類型,編譯器將幫助你遵守自己的規則。它可以聲明如下:

template<class T1, class T2> 
class Map{ 
    T1 key; 
    T2 value; 
    (...) 
} 

然後你就可以或多或少像這樣使用它:

Map<std::String, int> phoneBook; 

而且編譯器會守護你並警告,如果你嘗試添加,例如浮動,而不是的int,給你地圖。但是在你開始編碼之前,我建議你先閱讀一些教程,或者甚至是一些關於C++的書。但是如果你想現在就開始與通用的,你就可以開始她:

http://www.cplusplus.com/doc/tutorial/templates/

+0

哦,我已經使用Map,Multimap,Node和Graph模板實現了整個項目,但是現在的任務是使用繼承。 –

0

你可以將一個字符串存儲在你的對象變量的唯一途徑是,如果string類從Object繼承類,所以你將不得不實現你自己的String類。

這裏的真正缺陷是您正在採用Java/C#方法進行設計,其中Object變量可以容納任何東西。在C++中,處理這些事情的正確方法是使用模板,假設您的Map/Multimap/Node只需要保存一種特定的數據類型。

如果您的容器需要能夠保存任意數據類型,我會建議使用類型擦除,儘管對於初學者來說這可能有點複雜。

+0

正如我在之前的回答中所評論的,我已經完全用模板做了一個工作版本,但我的老師現在要求廢除這個,並且使用繼承來完成作業,他可能會有點偏離焦點嗎? –

+0

@JulioCalderón如果你的老師想讓你學習繼承..但是恕我直言這不是最好的例子(這是你寧願使用模板的地方 - 由於這個原因,標準容器庫由模板組成)。 – dyp

+0

好吧,我猜這不是最好的方法使用它,考慮到使用它沒有太多的好處,我只是創建自己的字符串類,因爲我沒有太多時間來打開它。 –