I found an example where redeclaring pure virtual method is required. Both gcc 10 and clang 11 requires the repeated declaration when the pure virtual method is used in the implementation of a descendant class itself abstract. Here is an example :
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;
}
As such, this programs does not link. I get the following error:
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)
And it is worst if I try other call to apply
in main (compilation error in this case, linked to the warning).
To make it works, I need to write the MTransition
class like this:
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;
}
};
But I do not succeed into calling t.apply(&d1, &d2);
in main. It seems to me that the definition of apply(int*p, double*e)
in TransitionTest
hides (as stated by the warning) the other apply
that should have been inherited.
EDIT (again): I found the solution in c++ overloaded virtual function warning by clang?
When overloading (or partially overwriting) a method in a derived class, one needs to use the using Base::method
to keep the other overloaded methods.
It gives:
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;
}