2016-02-29 34 views
0

我正在通過製作一個通用的List類來學習繼承。 List可以是Unordered列表,Ordered列表,StackQueue太少的參數繼承C++

List類看起來是這樣的:

class List 
{ 
public: 

    class Node 
    { 
    public: 
     int data; 
     Node * next; 
     Node(int data); 
    }; 

    int sizeOfList = 0; 
    Node * head = nullptr; 
    List::List(); 
    virtual void get(int pos); 
    virtual void insert(int data); 
    virtual void remove(int pos); 
    virtual void list(); 
    virtual int size(); 
}; 

Unordered列表類看起來是這樣的:

class UnOrderedList : public List 
{ 
public: 
    UnOrderedList(); 

    void get(); 
    void insert(int data); 
    virtual void remove(); //takes no parameters because first item is always removed 
}; 

main(),我像這樣創建列表的數組;

List * lists[8]; 

,使一個無序列表如下:

lists[0] = new UnOrderedList(); 

我的問題: lists[listNum]->get();給出錯誤

「在函數調用的參數太少」

,因爲它認爲我試圖在List類中調用get(),但我希望它調用無序列表的函數get()

+0

因爲它如何知道'lists [0]'指向UnOrderedList,而不是SomeOtherRandomList? – immibis

回答

2

我覺得我必須改進Sam Varshachik的回答 - 雖然他完全正確。

class List 
{ 
public: 
    virtual void get(int pos); 
}; 
class UnOrderedList : public List 
{ 
public: 
    void get(); 
}; 

請注意,這裏有兩個問題 - 不只是一個。

首先的get(int)簽名是get()不同 - 這些都是兩種不同的方法,編譯器會這樣對待他們。
而且你已經聲明,該方法List::get(int)是虛擬的,但你沒有這樣做,所以UnOrderedList::get() - 請記住,list對象有沒有關於它的知識的孩子 - 這樣一個list *無法理解的UnOrderedList細節。

考慮這個例子:

class List 
{ 
public: 
    virtual void get(int pos); 
}; 
class UnOrderedList : public List 
{ 
public: 
    virtual void get(); //STILL AN ERROR! 
}; 

在這種情況下,我已經UnOrderedList::get()虛擬 - 然而,這不會幫助。由於列表仍然不知道這種方法

正確的片段如下:

class List 
{ 
public: 
    virtual void get(int pos); 
    virtual void get(); 
}; 
class UnOrderedList : public List 
{ 
public: 
    virtual void get(); //We can use this now! 
    virtual void get(int pos); //This is only needed if we intend to override this method 
}; 

在這個例子中list::get()現在是一個虛擬的方法 - 因爲它這種任何的通話將被傳遞給正確的,孩子,你打算。
這是唯一可能的,但是因爲父類已被告知存在此類方法,並且可能被子類覆蓋。

[編輯/]

由於JonathanPotter在評論中指出,要注意一個事實,如果你希望有一個從父指針調用的方法被路由到只需要虛擬關鍵字實際的孩子對象。這確實會產生一些開銷。

+0

請注意,'UnOr​​deredList'中的方法不需要聲明爲'virtual',除非您希望能夠在從UnOrderedList繼承的類中重寫它們。 –

+0

@JonathanPotter - 好點!我想我會添加一個編輯。 –

+0

你的最後一句話看起來不符合喬納森的話。 – immibis

2

您需要在List類中聲明get()作爲虛方法。不是那個,還是dynamic_cast吧。

當您使用指向List的指針調用get()時,該特定指針可指向List的任何子類。僅僅因爲List的一個特定的子類實現了特定的方法並不意味着您可以使用指向基類的指針直接調用它。

否則,沒有必要擁有基類。這正是虛擬方法的用途:允許您使用指向基類的指針來調用子類中的方法。

+0

也許我看着錯誤的東西,但不是我已經在List類中聲明get()作爲虛擬方法了嗎? –

+0

我是否也需要聲明get(int)? –

+1

您正在將get(int)聲明爲虛方法。您沒有將get()聲明爲虛方法。 get(int)和get()是兩種完全不同的方法。 –

1

lists[0]是一個List*就編譯器而言。

UnOrderedList::get()將不會覆蓋List::get(int pos),因爲簽名是不同的。如果您希望派生類重寫基類中的函數,則函數簽名必須相同。

事實上,您需要投下lists[listNum]UnOrderedList*才能撥打UnOrderedList::get(),例如, static_cast<UnOrderedList*>(lists[listNum])->get()

+0

我明白你在說什麼,但我想用listNum來訪問子類的類型,並避免投射。我的想法是不合理的嗎?有沒有辦法避免使用4個不同的if()鑄造語句來鑄造? –

+0

@TysiaKrepps我認爲你不明白。 'UnOrderedList :: get()'不會覆蓋基類中的函數,因爲它沒有使用'List :: get()'所帶的'int pos'參數。 –