1

这是我试图实现的粗略图像(它不会编译,所以认为它是伪代码)。请注意,尽管该示例基于公钥密码方案,但问题是关于设计模式、模板和继承。

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只是需要创建一个变量并调用另一个函数,那么我不想在每个派生类中都编写这段代码,但是,如果派生类需要对数据进行一些额外的处理,它应该能够覆盖基础方法。

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

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

4

4 回答 4

2

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

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

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

恕我直言,这里不需要 CRTP。

于 2012-07-18T14:45:10.840 回答
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 模板时,该基类必须是完整类型。下面的代码不起作用,至少在 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();
    }
};
于 2012-07-18T14:34:05.990 回答
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;
 }
于 2012-07-18T15:11:39.447 回答
0

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

当然,根据您要执行的操作,此答案可能是对还是错。

于 2012-07-18T14:29:09.860 回答