我有以下结构继承:
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),这就是问题所在。
答案 0 :(得分:4)
在将函数定义与现有声明匹配的情况下,C ++不会考虑继承。您已声明void foo(Base s);
,并且只应该定义它。但是既然你需要重载,你应该有两个声明:
void foo(ChildOne s);
void foo(ChildTwo s);
此外,您可以void foo(T s);
重载,其中T
是指针或对Base
或const Base
的引用。传递Base
或派生类与ChildOne
和ChildTwo
不同时,将调用此重载。
修改强>
在阅读了我跳过的笔记部分后,无法使用std::queue<Base>
的元素进行上述工作,这些元素都是Base
s。如果您在push
或ChildOne
中尝试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。函数声明和定义必须完全匹配。