重载以结构继承作为参数的函数 C++

Overloading functions with struct inheritance as arguments c++

我有以下结构继承:

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) 识别为潜在候选者)。我对重载函数和继承有什么误解?

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

如果您希望 ChildOne 和 ChildTwo 有一个成员函数,您还必须声明 zwo 成员函数(一个用于 childOne,一个用于 ChildTwo)。

就函数重载而言,它是完全无关紧要的,例如ChildOne 派生自 Base。函数声明和定义必须完全匹配。

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

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

此外,您可以有 void foo(T s); 重载,其中 T 是对 Baseconst Base 的指针或引用。当传递不同于 ChildOneChildTwo.

Base 或派生的 类 时将调用此重载

编辑:

在阅读了我跳过的注释部分后,无法使用 std::queue<Base> 的元素进行上述操作,这些元素都是 Base。如果您尝试在 ChildOneChildTwopush,该对象将获得 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