我发现了一个需要重新声明纯虚方法的示例。 gcc 10 和 clang 11 都需要在纯虚方法用于实现后代类本身抽象时重复声明。这是一个例子:
class Transition {
public:
virtual int* apply(int*p, double*e) = 0;
virtual long* apply(double*h, double*e) = 0;
virtual long* apply(long* l, double *e) { return l;}
};
class MTransition : public Transition {
public:
//virtual int* apply(int*p, double*e) = 0; // duplicate from upper class but required
virtual long* apply(double*h, double*e) {
int a= *(Transition::apply((int*)h, e)); // not resolved correctly without the duplicate declaration
return a?nullptr:nullptr;
}
};
class TransitionTest : public MTransition {
public:
virtual int* apply(int*p, double*e) { return p; }
};
int main() {
TransitionTest t;
double /*d1=1.0,*/ d2=2.0;
int i1=1;
/*int *pi = t.apply(&d1, &d2); */
int *pi = t.apply(&i1, &d2);
return pi?(*pi):0;
}
因此,此程序不链接。我收到以下错误:
clang++ -Wall yo.cpp
yo.cpp:19:16: warning: 'TransitionTest::apply' hides overloaded virtual function [-Woverloaded-virtual]
virtual int* apply(int*p, double*e) { return p; }
^
yo.cpp:11:17: note: hidden overloaded virtual function 'MTransition::apply' declared here: type mismatch at 1st parameter ('double *' vs 'int *')
virtual long* apply(double*h, double*e) {
^
1 warning generated.
/usr/bin/ld: /tmp/yo-cb0979.o: in function `MTransition::apply(double*, double*)':
yo.cpp:(.text._ZN11MTransition5applyEPdS0_[_ZN11MTransition5applyEPdS0_]+0x27): undefined reference to `Transition::apply(int*, double*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
如果我在 main 中尝试对apply 进行其他调用,则最糟糕的是(在这种情况下是编译错误,与警告相关联)。
为了让它工作,我需要像这样编写MTransition 类:
class MTransition : public Transition {
public:
virtual int* apply(int*p, double*e) = 0; // duplicate from upper class but required
virtual long* apply(double*h, double*e) {
int a= *(apply((int*)h, e)); // not resolved correctly without the duplicate declaration
return a?nullptr:nullptr;
}
};
但我没有成功在 main 中调用 t.apply(&d1, &d2);。在我看来,TransitionTest 中的 apply(int*p, double*e) 的定义隐藏了(如警告所述)另一个应该被继承的 apply。
编辑(再次):我在c++ overloaded virtual function warning by clang? 中找到了解决方案
在派生类中重载(或部分覆盖)方法时,需要使用using Base::method 来保留其他重载的方法。
它给出:
class Transition {
public:
virtual int* apply(int*p, double*e) = 0;
virtual int* apply(double*h, double*e) = 0;
virtual int* apply(long* l, double *e) { std::cerr << "Transition::apply(long*,double*)" << std::endl; return nullptr;}
};
class MTransition : public Transition {
public:
using Transition::apply;
virtual int* apply(double*h, double*e) {
std::cerr << "MTransition::apply(double*,double*)" << std::endl;
int a= *(apply((int*)h, e)); // not resolved correctly without the duplicate declaration
return a?nullptr:nullptr;
}
};
class TransitionTest : public MTransition {
public:
using MTransition::apply;
virtual int* apply(int*p, double*e) { std::cerr << "TransitionTest::apply(int*,double*)" << std::endl; return p; }
};
int main() {
TransitionTest t;
double d1=1.0, d2=2.0;
//int i1=1;
int *pi = t.apply(&d1, &d2);
//int *pi = t.apply(&i1, &d2);
return pi?(*pi):0;
}