在复制构造函数中使用 *this 作为 const 来克隆自身

Using *this as const in copy constructor to clone self

我正在尝试实现一个原型 pattern.When 我使用 *this 传递自身对象以便使用复制构造函数克隆自身 由于以下原因我无法访问自身成员函数:

error: passing ‘const ConcreteClonable1’ as ‘this’ argument discards qualifiers [-fpermissive]

错误与 const 的错误使用有关。但是,如果我从复制构造函数中删除 const 一切正常。我想按预期使用复制构造函数,使用 const 参数,并能够访问非常量 class 成员。

代码如下:

/* Prototype base class. */
class Prototype
{
    protected:
        std::string type;
        int value;
    public:
        virtual Prototype* clone() = 0;
        std::string getType() { return type; }
        int getValue() { return value; }
};

//clonable class
class ConcreteClonable1 : public Prototype
{
    public:
        ConcreteClonable1(int number)
        {
            std::cout << "ConcreteClonable1 cnstr\n";
            type  = "Type1";
            value = number;
        }
        //compilation error if const is used
        ConcreteClonable1 (const ConcreteClonable1& x)
        {
            std::cout << "ConcreteClonable1 copy cnstr\n";
            type  = x.getType();
            value = x.getValue();
        }
        Prototype* clone() { return new ConcreteClonable1(*this); }
};

对象在 Factory 中初始化。

问题是为什么会这样?有没有更好的方法来使用来自 c++ STL 的某种 copy 函数来做到这一点?

你的 const 无处不在。直接的问题是 getTypegetValue 需要标记为 const 否则如果隐式 this 指针是 const,它们将无法使用,它位于你的情况。

除此之外,您还应该将 clone() 函数也修复为 const(尽管这对于您的即时编译问题不是必需的):

Prototype* clone() const { return new ConcreteClonable1(*this); }

克隆毕竟不应该修改当前对象。

您试图在 ConcreteClonable1 的复制构造函数中对 ConcreteClonable1 : public Prototype 的常量对象调用 Prototype 的非常量成员函数。要使其工作,您必须将它们设置为常量(或者根本不使用它们,请参见下文)。

除此之外,您实际上不需要了解 Prototype 即可复制 ConcreteClonable1。只需复制成员即可。

只需委托Prototype

的复制构造
ConcreteClonable1::ConcreteClonable1(const ConcreteClonable1 & x) : Prototype(x) 
{ std::cout << "ConcreteClonable1 copy cnstr\n"; }

一般来说,你应该更喜欢成员初始化而不是在构造函数的主体中赋值。

Prototype::Prototype(std::string type_, int value_) : type(type_), value(value_) {}

ConcreteClonable1::ConcreteClonable1(int number) : Prototype("Type1", number) 
{ std::cout << "ConcreteClonable1 cnstr\n"; }