我有以下问题。类E
覆盖了两种方法:一种来自抽象类D
,该抽象类继承自模板类C<T>
的特殊化,其中T = A
。另一个直接来自C<A>
。两者的名字相同。
现在,D
应该可以访问这两种方法:doSomething(const A& a)
因为它是从C
继承的,而doSomething(const B& b)
是因为D
声明了它。
但是,以下代码无法编译,因为编译器只能从指向doSomething(const B&)
的指针中识别方法D
#include <iostream>
#include <sstream>
using namespace std;
class A {
private:
int a = 10;
public:
inline std::string hello() const{
std::stringstream ss;
ss << a;
return ss.str();
}
};
class B {
private:
int b = 20;
public:
inline std::string hello() const{
std::stringstream ss;
ss << b;
return ss.str();
}
};
template <class T>
class C {
public:
inline virtual bool doSomething(const T& t) {
std::cout << "C is doing something with T" << t.hello() << std::endl;
return true;
}
};
class D : public C<A> {
public:
virtual void doSomething(const B& b) = 0;
};
class E : public D {
public:
inline bool doSomething(const A& a) override {
std::cout << "E is doing something with A: " << a.hello() << std::endl;
return true;
}
inline void doSomething(const B& b) override {
std::cout << "E is doing somethign with B: " << b.hello() << std::endl;
}
};
int main()
{
A a;
B b;
D* d = new E();
d->doSomething(b);
d->doSomething(a); // compile error, does not recognize doSomething(const A&)
delete d;
}
编译器显示以下错误:
In function ‘int main()’:
main.cpp:62:19: error: no matching function for call to ‘D::doSomething(A&)’
d->doSomething(a); // compile error, does not recognize doSomething(const A&)
^
main.cpp:39:18: note: candidate: virtual void D::doSomething(const B&)
virtual void doSomething(const B& b) = 0;
^
main.cpp:39:18: note: no known conversion for argument 1 from ‘A’ to ‘const B&’
那是为什么?
答案 0 :(得分:2)
之所以发生这种情况,是因为编译器不会自动将基类中的所有功能合并到要选择的重载功能集中。那就是当您调用d->doSomething(a);
仅由D::doSomething(const B& b)
组成的一组重载函数。为了解决这个问题,您需要将C<A>::doSomething;
纳入D
类
class D : public C<A> {
public:
using C<A>::doSomething;
virtual void doSomething(const B& b) = 0;
};
答案 1 :(得分:1)
要使基类函数在派生类中可见并被同名函数隐藏,应使用using
指令(using C<A>::doSomething;
)。
但是,我还想补充一点,当您delete d
时,GCC 8.2报告代码中存在未定义的行为。这是因为类D
具有非虚拟的析构函数。
warning: deleting object of abstract class type 'D' which has non-virtual destructor will cause undefined behavior [-Wdelete-non-virtual-dtor]
delete d;
请参见demo here。