简体   繁体   English

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

[英]Overloading functions with struct inheritance as arguments c++

I have the following struct inheritance: 我有以下结构继承:

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
  }
};

If I want to have an overloaded function, one that handles the case when a ChildOne struct is passed, and one for ChildTwo, how would I implement that? 如果我想要一个重载函数,一个在传递ChildOne结构时处理这个情况的函数,以及一个用于ChildTwo的函数,我将如何实现它?

What I'm currently trying: In hpp: 我正在尝试的内容:在hpp中:

class MyClass
{
  void foo(Base s);
}

In cpp: 在cpp中:

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

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

If I understand inheritance correctly, ChildOne and ChildTwo are both Base. 如果我正确理解继承,ChildOne和ChildTwo都是Base。 I should be able to pass ChildOne to this foo function because ChildOne IS a Base. 我应该能够将ChildOne传递给这个foo函数,因为ChildOne是一个Base。 But this doesn't compile for me, saying it can't find a find a matching prototype in MyClass (but it does recognize foo(Base) as a potential candidate). 但这不能为我编译,说它找不到在MyClass中找到匹配的原型(但它确实将foo(Base)识别为潜在的候选者)。 What am I misunderstanding about overloading functions and inheritance? 我对重载函数和继承有什么误解?

note: The reason I have a base class with empty children inheriting it was so I could have a std::queue<Base> that would only hold ChildOne or ChildTwo structs, no Base structs. 注意:我有一个基类与继承它的空子的原因是我可以有一个std::queue<Base>只能保存ChildOne或ChildTwo结构,没有Base结构。 This works beautifully. 这很好用。 It's calling an overloaded function to handle the front item of the queue (whether it's a ChildOne or ChildTwo) that's the problem. 它正在调用一个重载函数来处理队列的前端项(无论是ChildOne还是ChildTwo),这就是问题所在。

C++ doesn't take inheritance into account in cases like matching function definition with existing declaration. 在将函数定义与现有声明匹配的情况下,C ++不会考虑继承。 You have declared void foo(Base s); 你已经声明了void foo(Base s); and only that should be defined. 只有那个应该被定义。 But since you need overloads, you should have two declarations instead: 但是既然你需要重载,你应该有两个声明:

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

Additionally, you can have void foo(T s); 另外,你可以有void foo(T s); overload, where T is a pointer or a reference to Base or const Base . 重载,其中T是指针或对Baseconst Base的引用。 This overload will be called when passing Base or derived classes different to ChildOne and ChildTwo . 传递与ChildOneChildTwo不同的Base或派生类时,将调用此重载。

EDIT: 编辑:

After reading the note part which I skipped over, there's no way of making the above work with elements of std::queue<Base> , which are all Base s. 在阅读了我跳过的笔记部分之后,没有办法使用std::queue<Base>元素进行上述工作,这些元素都是Base s。 If you try to push in ChildOne or ChildTwo , the object gets sliced . 如果您尝试pushChildOneChildTwo ,则对象会被切片

If you had std::queue<Base*> or std::queue<std::shared_ptr<Base>> which support polymorphism, *myQueue.front() would still try to match the overload taking Base as an argument. 如果你有支持多态的std::queue<Base*>std::queue<std::shared_ptr<Base>>*myQueue.front()仍会尝试匹配以Base为参数的重载。 Nonetheless, you should take a look at polymorphism, because I think that's what should be used here. 尽管如此,你应该看看多态性,因为我认为这应该是在这里使用的。 I hope this example will make you interested if you're not already. 我希望这个例子会让你感兴趣,如果你还没有。

#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();
    }
}

Output ( Coliru ): 输出( Coliru ):

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

If you want to have one member function for ChildOne and ChildTwo you also have to declare zwo memberfunctions (one for childOne anf one for ChildTwo). 如果你想为ChildOne和ChildTwo提供一个成员函数,你还必须声明zwo成员函数(一个用于childOne,一个用于ChildTwo)。

As far as functio overloading is concerned, it is completely irrelevant that eg ChildOne is derived from Base. 就函数重载而言,例如ChildOne派生自Base是完全无关紧要的。 Function declaration and definition have to match exactly. 函数声明和定义必须完全匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM