用抽象返回类型设计继承

时间:2012-07-18 14:01:38

标签: c++ templates design-patterns inheritance abstract-class

这是我正在尝试实现的粗略图像(它不会编译,因此请考虑伪代码)。请注意,即使该示例基于公钥加密方案,问题仍然是设计模式,模板和继承。

class CryptoProvider
{
public:
    template <typename T>
    virtual T Encrypt ()
    {
        T data;

        return data;
    }
};

class Paillier : public CryptoProvider
{
public:
    typedef int Ciphertext;

    Ciphertext Encrypt ()
    {
        Ciphertext data;
        return data;
    }
};

class ElGamal : public CryptoProvider
{
public:
    struct Ciphertext
    {
    public:
        int c1;
        int c2;
    };

    Ciphertext Encrypt ()
    {
        Ciphertext data;
        return data;
    }
};

基本上,我想在CryptoProvider中提供一些通用功能,如果需要,可以由派生类覆盖,否则我最终会遇到大量重复代码。如果Encrypt只需要创建一个变量并调用另一个函数,那么我不想在每个派生类中编写这个代码,但是,如果派生类需要对数据做一些额外的处理,它应该能够覆盖基本方法。

我遇到的最大限制是以某种方式通过指定完全不同的返回类型来覆盖加密功能。有人能指出我如何实现这个目标吗?我应该坚持传统继承还是应该尝试使用CRTP进行编译时/静态多态?我不知道从哪里开始。

我还想强制派生类来实现某些方法,但我不知道如何实现这一点,如果第一个问题的解决方案要求我放弃标准继承(我不会从虚方法中受益) )...

4 个答案:

答案 0 :(得分:2)

您的所有子类都将Ciphertext类型定义为不同的东西。这建议将其设为CryptoProvider的模板参数。

template <typename T>
class CryptoProvider
{
public:
    virtual T Encrypt () { ... }
    typedef T Ciphertext;
};

class PaillierBase : public CryptoProvider<int> { ... }

这里不需要恕我直言CRTP。

答案 1 :(得分:1)

CRTP将在不需要虚函数的情况下提供编译时可重写的功能:

template <typename Derived> class CryptoProvider
{
public:
    typename Derived::Ciphertext Encrypt() {
        typename Derived::Ciphertext data;
        return data;
    }
};

class PaillierBase
{
public:
    typedef int Ciphertext;
};

class Paillier : public CryptoProvider<PaillierBase>
{
public:
    void test1() {
        Encrypt();
    }
};

class ElGamalBase
{
public:
    struct Ciphertext {
        int c1;
        int c2;
    };
};

class ElGamal : public CryptoProvider<ElGamalBase>
{
public:
    void test2() {
        Encrypt();
    }
};

返回类型需要在基类中声明,当从您派生CRTP模板时,CRTP模板实例化时必须是完整类型。下面的代码不起作用,至少在C11之前的编译器中:在P点,ElGamal类还不是一个完整的类型,因此无法实例化CryptoProvider :: Encrypt()。我不知道C11在这里是否有任何改变。这是语言的愚蠢缺点,恕我直言。

// Doesn't work, unfortunately
class ElGamal : public CryptoProvider<ElGamal> /* P */
{
public:
    struct Ciphertext {
        int c1;
        int c2;
    };
    void test2() {
        Encrypt();
    }
};

答案 2 :(得分:1)

查看实现此目的的另一种方法。略微圆润,但...... 这提供了基于模板和可导出性的通用实现的可能性。唯一的问题是CipherText定义不能在派生类中。我想这对你来说不是一个大问题。如果您可以在全局范围内定义这些类,则可以避免使用其他派生。

template <typename T>
class CryptoProvider
{

public:
    virtual T Encrypt()
    {
        T data;

        return data;
    }
};

class PaillierBase
{
public:
   typedef int Ciphertext;
};

class Paillier : public PaillierBase, public CryptoProvider<PaillierBase::Ciphertext>
{
public:

};

class ElGamalBase
{
public:
    struct Ciphertext
    {
    public:
        int c1;
        int c2;
    };


};

class ElGamal : public ElGamalBase, public CryptoProvider<ElGamalBase::Ciphertext>
{
public:

};

class CustomEncryptorBase
{
public:
    struct Ciphertext
    {
    public:
        char* c1;
        int* c2;
    };


};

class CustomEncryptor : public CustomEncryptorBase, public CryptoProvider<CustomEncryptorBase::Ciphertext>
{
public:

    virtual CustomEncryptorBase::Ciphertext Encrypt()
    {
        CustomEncryptorBase::Ciphertext data;

        //  Do additional processing

        return data;
    }
};

int main()
{
    ElGamal e;
    ElGamalBase::Ciphertext c = e.Encrypt();

    CustomEncryptor ce;
    CustomEncryptorBase::Ciphertext c1 = ce.Encrypt();

    return 0;
 }

答案 3 :(得分:0)

您可以创建一个名为CipherText的基类,您可以在其中保存密文。然后,您可以将其子类化为您需要返回的特定类型。您可以将返回类型指定为基类指针。

当然,根据您的目的,这个答案可能是正确的或错误的。