I have below as 'simple' of an example of what I am trying to do as I could think up. I have an abstract class A
which exposes a public interface to the world with two methods: operator==
and performTasksSpecificToA
. You can see that I'm using the 'Template Method Pattern' as well as the 'curiously recurring template pattern' in order to ensure that users of A
don't need to worry about the implementation of A
, in other words AImpl
, while still being able to check equality against two instances of AImpl
. See this answer on SO for a bit more information and context on this approach.
Now, suppose I wish to define a class B
as follows:
class B
{
public:
virtual ~B() = 0;
bool operator(const B& b) const;
void performTasksSpecificToB();
};
As you can see, class B
shares the same problem as A
in terms of defining a public operator==
for comparing sub-classes. How can I define a parent-class, let's call it Letter
, in order to avoid duplicating code between A
and B
?
Here is my 'simple example', which compiles and runs.
#include <iostream>
class A
{
public:
virtual ~A() = 0;
bool operator==(const A& a) const;
void performTasksSpecificToA();
private:
virtual bool checkEquality_(const A& a) const = 0;
};
template <class T>
class A_ : public A
{
protected:
bool checkEquality_(const A& a) const override;
private:
virtual bool checkEquality(const T& t) const = 0;
};
class AImpl : public A_<AImpl>
{
public:
AImpl(int val) : val(val){};
bool checkEquality(const AImpl& anAImpl) const override;
private:
int val;
};
A::~A(){}
bool A::operator==(const A& a) const{
return checkEquality_(a);
}
template <class T>
bool A_<T>::checkEquality_(const A& a) const{
const T* other = dynamic_cast<const T*>(&a);
if (other != nullptr){
const T& me = static_cast<const T&>(*this);
return other->checkEquality(me);
}
return false;
}
bool AImpl::checkEquality(const AImpl& anAImpl) const{
return val == anAImpl.val;
}
int main(){
// factory:
AImpl* aImpl1 = new AImpl(1);
AImpl* aImpl2 = new AImpl(2);
AImpl* aImpl3 = new AImpl(1);
// client:
A& A1 = *aImpl1;
A& A2 = *aImpl2;
A& A3 = *aImpl3;
std::cout << "A1 == A2 -> ";
std::cout << (A1 == A2 ? "true" : "false");
std::cout << std::endl;
std::cout << "A1 == A3 -> ";
std::cout << (A1 == A3 ? "true" : "false");
std::cout << std::endl;
delete aImpl1;
delete aImpl2;
delete aImpl3;
return 0;
}
Aucun commentaire:
Enregistrer un commentaire