参数继承太少c ++

时间:2016-02-29 03:25:16

标签: c++ inheritance

我正在通过制作通用List类来学习继承。 List可以是Unordered列表,Ordered列表,StackQueue

我的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();出错

  

“函数调用中的参数太少”

因为它认为我试图在get()类中调用List,但我希望它调用无序列表的函数get()

3 个答案:

答案 0 :(得分:2)

您需要在get()类中声明List作为虚拟方法。要么是,要么是dynamic_cast

当您使用指向get()的指针调用List时,该特定指针可以指向List的任何子类。仅仅因为List的一个特定子类实现了一个特定的方法并不意味着你可以使用指向基类的指针直接调用它。

否则,没有必要拥有基类。这正是虚拟方法的用途:允许您使用指向基类的指针调用子类中的方法。

答案 1 :(得分: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()现在是一个虚拟方法 - 因此,对它的任何调用都将按照您的意图传达给正确的子项。
这是唯一可能的,因为父类已被告知存在这样的方法,并且可以被子类覆盖

[edit /]

正如JonathanPotter在评论中所述,请注意只有当您希望将从父指针调用的方法路由到实际子对象时才需要虚拟关键字。而这确实会产生一些开销。

答案 2 :(得分:1)

就编译器而言,

lists[0]List*

UnOrderedList::get()不会覆盖List::get(int pos),因为签名不同。如果希望派生类覆盖基类中的函数,则函数签名必须相同。

实际上,您需要将lists[listNum]投射到UnOrderedList*以致电UnOrderedList::get(),例如static_cast<UnOrderedList*>(lists[listNum])->get()