使用struct继承作为参数c ++重载函数

时间:2015-08-25 22:45:31

标签: c++ inheritance struct overloading

我有以下结构继承:

struct Base
{
  Base(int a, int b)
    : m_a(a), m_b(b)
  {
    // empty
  }

  int m_a;
  int m_b;
};

struct ChildOne: public Base
{
  ChildOne(int a, int b)
    : Base(a, b)
  {
    // empty
  }
};

struct ChildTwo: public Base
{
  ChildTwo(int a, int b)
    : Base(a, b)
  {
    // empty
  }
};

如果我想要一个重载函数,一个在传递ChildOne结构时处理这个情况的函数,以及一个用于ChildTwo的函数,我将如何实现它?

我目前正在尝试的内容: 在hpp:

class MyClass
{
  void foo(Base s);
}

在cpp:

void Myclass::foo(ChildOne s)
{
  //Do things specific for ChildOne
}

void MyClass::foo(ChildTwo s)
{
  //Do things specific for ChildTwo
}

如果我正确理解继承,ChildOne和ChildTwo都是Base。我应该能够将ChildOne传递给这个foo函数,因为ChildOne是一个Base。但这并没有为我编译,说它无法在MyClass中找到匹配的原型(但 认识到foo(Base)是潜在的候选者)。我对重载函数和继承有什么误解?

注意:我有一个基类继承它的空子的原因是我可以有std::queue<Base>只能保存ChildOne或ChildTwo结构,没有Base结构。这很好用。它调用一个重载函数来处理队列的前面项目(无论是ChildOne还是ChildTwo),这就是问题所在。

2 个答案:

答案 0 :(得分:4)

在将函数定义与现有声明匹配的情况下,C ++不会考虑继承。您已声明void foo(Base s);,并且只应该定义它。但是既然你需要重载,你应该有两个声明:

void foo(ChildOne s);
void foo(ChildTwo s);

此外,您可以void foo(T s);重载,其中T是指针或对Baseconst Base的引用。传递Base或派生类与ChildOneChildTwo不同时,将调用此重载。

修改

在阅读了我跳过的笔记部分后,无法使用std::queue<Base>的元素进行上述工作,这些元素都是Base s。如果您在pushChildOne中尝试ChildTwo,则对象获得sliced

如果您有std::queue<Base*>std::queue<std::shared_ptr<Base>>支持多态,*myQueue.front()仍会尝试匹配以Base为参数的重载。尽管如此,你应该看看多态性,因为我认为这应该是在这里使用的。我希望这个例子会让你感兴趣,如果你还没有。

#include <iostream>
#include <queue>
using std::cout;
using std::endl;

struct Base
{
    Base(int a, int b) : m_a(a), m_b(b) {}
    virtual ~Base() = default;

    virtual void doSomething() = 0; // pure virtual (must be defined by deriving classes)

    int m_a;
    int m_b;
};

struct ChildOne : public Base
{
    ChildOne(int a, int b) : Base(a, b) {}

    virtual void doSomething() override
    {
        cout << "ChildOne doing something" << endl;
    }
};

struct ChildTwo : public Base
{
    ChildTwo(int a, int b) : Base(a, b) {}

    virtual void doSomething() override
    {
        cout << "ChildTwo doing something" << endl;
    }
};

class MyClass
{
public:
    void foo(Base *b)
    {
        b->doSomething(); // polymorphism will take care of calling the right function
    }
};

int main()
{
    MyClass c;
    std::queue<Base*> queue;
    queue.push(new ChildOne(1, 2));
    queue.push(new ChildTwo(1, 2));
    queue.push(new ChildTwo(1, 2));
    queue.push(new ChildOne(1, 2));

    while(!queue.empty())
    {
        c.foo(queue.front());
        delete queue.front();
        queue.pop();
    }
}

输出(Coliru):

ChildOne doing something
ChildTwo doing something
ChildTwo doing something
ChildOne doing something

答案 1 :(得分:0)

如果你想为ChildOne和ChildTwo提供一个成员函数,你还需要声明zwo成员函数(一个用于childOne,一个用于ChildTwo)。

就函数重载而言,与例如完全无关。 ChildOne源自Base。函数声明和定义必须完全匹配。