2017-08-02 37 views
0

我有下面这样简单的例子来说明我想要做的事情。我有一个抽象类A,它通过两种方法向世界公开了一个公共接口:operator==performTasksSpecificToA。您可以看到我正在使用“模板方法模式”以及“奇怪的循环模板模式”,以确保A的用户不需要担心A的执行,换句话说就是AImpl,而仍然能够检查对两个AImpl两个实例的平等。有关此方法的更多信息和上下文,请参阅this answer on SO如何定义一个父类来减少代码重复,同时使用具有相等运算符定义的抽象类?

现在,假设我希望定义一个类B如下:

class B 
{ 
    public: 
     virtual ~B() = 0; 

     bool operator(const B& b) const; 
     void performTasksSpecificToB(); 
}; 

正如你可以看到在界定公共operator==用于比较的子类而言,类B股同样的问题A。我如何定义父级,我们称之为Letter,以避免在AB之间重复代码?


这是我的'简单的例子',它编译和运行。

#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; 
} 
+0

为什么在平等比较中有这么多层次的间接性? –

+0

第一级是为了避免使'A'成为模板类:因此,我将实际的逻辑移到了'A_'。第二个层次,即使用'A :: checkEquality_'是为了区分'A'公开曝光的方法和需要被子分类占据的部分(根据'模板方法模式')。 – wesanyer

回答

0

如果你可以让Letter是一个模板,你可以简单地具有从模板库A继承:

template<class T> 
class Letter 
{ 
public: 
    bool operator==(const Letter<T>& t) const { 
     const T& t1 = static_cast<const T&>(*this); 
     const T& t2 = static_cast<const T&>(t); 
     return t1.checkEquality_(t2); 
    } 
private: 
    virtual bool checkEquality_(const T& a) const = 0; 
}; 

class A : public Letter<A> 
{ 
    public: 
     virtual ~A() = 0; 
     void performTasksSpecificToA(); 
}; 
... 

如果你绝对需要一个共同的Letter,你可能要添加另一层的CRTP,就像你用A_A做的那样。

相关问题