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

时间:2018-02-07 12:31:19

标签: c++ const clone copy-constructor

我正在尝试实现原型模式。当我使用*this传递自身对象以便使用复制构造函数克隆自身时,由于以下原因我无法访问自身成员函数:

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

错误与const的错误使用有关。但是,如果我从复制构造函数中删除const,一切正常。我想使用复制构造函数,因为它应该具有const参数,并且能够访问非const类成员。

以下是代码:

/* 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函数来完成这个?

3 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:2)

您正试图在Prototype的复制构造函数中调用ConcreteClonable1 : public Prototype的const对象上的ConcreteClonable1的非const成员函数。为了使它工作,你必须使它们成为常量(或根本不使用它们,见下文)。

除此之外,您并不需要了解Prototype来复制ConcreteClonable1。只需复制成员。

答案 2 :(得分:2)

只需委托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"; }