添加同名方法后继承的模板化方法不可见
inherited templated method not visible after method with same name is added
我有以下问题。 class E
覆盖了两种方法:一种来自抽象 class D
,它继承自模板化 class C<T>
的特化,其中 T = A
。另一个直接来自C<A>
。而且两者同名。
现在,D
应该可以访问两种方法:doSomething(const A& a)
因为它继承自 C
,doSomething(const B& b)
因为 D
声明了它。
但是,下面的代码编译不通过,因为编译器只从指向D
的指针识别方法doSomething(const B&)
#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&’
这是为什么?
发生这种情况是因为编译器不会自动将所有函数从基 class 合并到重载函数集到 select。那就是调用 d->doSomething(a);
时考虑的重载函数集仅由 D::doSomething(const B& b)
组成。为了解决这个问题,您需要将 C<A>::doSomething;
带入 D
class
class D : public C<A> {
public:
using C<A>::doSomething;
virtual void doSomething(const B& b) = 0;
};
要使基 class 函数在被同名函数隐藏的派生 class 中可见,您应该使用 using
指令(using C<A>::doSomething;
).
但是,我还想补充一点,当您 delete d
时,GCC 8.2 报告代码中存在未定义的行为。这是因为 class D
有一个非虚析构函数。
warning: deleting object of abstract class type 'D' which has non-virtual destructor will cause undefined behavior [-Wdelete-non-virtual-dtor]
delete d;
我有以下问题。 class E
覆盖了两种方法:一种来自抽象 class D
,它继承自模板化 class C<T>
的特化,其中 T = A
。另一个直接来自C<A>
。而且两者同名。
现在,D
应该可以访问两种方法:doSomething(const A& a)
因为它继承自 C
,doSomething(const B& b)
因为 D
声明了它。
但是,下面的代码编译不通过,因为编译器只从指向D
doSomething(const B&)
#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&’
这是为什么?
发生这种情况是因为编译器不会自动将所有函数从基 class 合并到重载函数集到 select。那就是调用 d->doSomething(a);
时考虑的重载函数集仅由 D::doSomething(const B& b)
组成。为了解决这个问题,您需要将 C<A>::doSomething;
带入 D
class
class D : public C<A> {
public:
using C<A>::doSomething;
virtual void doSomething(const B& b) = 0;
};
要使基 class 函数在被同名函数隐藏的派生 class 中可见,您应该使用 using
指令(using C<A>::doSomething;
).
但是,我还想补充一点,当您 delete d
时,GCC 8.2 报告代码中存在未定义的行为。这是因为 class D
有一个非虚析构函数。
warning: deleting object of abstract class type 'D' which has non-virtual destructor will cause undefined behavior [-Wdelete-non-virtual-dtor]
delete d;