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

Using *this as const in copy constructor to clone self [duplicate]

提问人:BugShotGG 提问时间:2/7/2018 最后编辑:BugShotGG 更新时间:2/9/2018 访问量:940

问:

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

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

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

代码如下:

/* 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 中的某种复制函数来做到这一点?

C++ 常量 clone copy-constructor

评论

1赞 463035818_is_not_an_ai 2/7/2018
为什么不呢?getTypeconst
1赞 463035818_is_not_an_ai 2/7/2018
根据经验,您可以创建所有方法,并且仅在需要修改时才将其删除constthis
1赞 Jonathan Wakely 2/7/2018
这个问题并不是关于原型模式,它只是“为什么我不能在 const 对象上调用这些成员函数?”,这个问题已经在 StackOverflow 上被问了一千次,答案是因为你没有制作成员函数。const
0赞 Caleth 2/7/2018
@JonathanWakely它还应该引发一个问题“我为什么要调用这些成员函数”
2赞 463035818_is_not_an_ai 2/7/2018
@Caleth甚至更好的是“我为什么首先写 getters?

答:

2赞 Bathsheba 2/7/2018 #1

你的正确性无处不在。眼前的问题是,如果隐式指针是 ,则需要标记,否则它们不能使用,在您的情况下是这样。constgetTypegetValueconstthisconst

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

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

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

评论

1赞 Sopel 2/7/2018
这不是问题。问题是他在 Copy CTOR 中使用了非常量成员函数
2赞 UKMonkey 2/7/2018
@Bathsheba 虽然 clone 不需要是 const;很多功能也没有。我会考虑将其作为修复的一部分进行更正
1赞 Caleth 2/7/2018
@UKMonkey 哦,对于时间机器,所以它可以是修饰符,并且是默认的mutableconst
1赞 Bathsheba 2/7/2018
@Caleth:当然。并删除,甚至可能也是如此。就此而言。事实上,这是一个类型,而不是一个.std::vector<bool>boolclass'c'charint
2赞 UKMonkey 2/7/2018
@Bathsheba查克·诺里斯获胜
2赞 Sopel 2/7/2018 #2

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

除此之外,你真的不需要知道复制。只需复制成员即可。PrototypeConcreteClonable1

评论

0赞 BugShotGG 2/7/2018
谢谢,制作和工作。我现在明白为什么会这样了。完全忘记了 和 的访问规则getTypegetValueconstconstnonconst
2赞 Caleth 2/7/2018 #3

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

评论

0赞 Sopel 2/7/2018
是的,那更好
0赞 BugShotGG 2/7/2018
@Caleth 谢谢你的回答。我有一个问题。为什么无需声明和 as 即可工作?: Prototype(x)getTypegetValueconst
0赞 Caleth 2/7/2018
因为有一个编译器生成的复制构造函数直接复制数据成员,并且不涉及Prototype::Prototype(const Prototype &)getTypegetValue
0赞 Caleth 2/7/2018
这就是为什么是可用的类型,例如struct pair { std::string first; int second; };pair one = { "just works", 1 }, two; two = one;
1赞 Caleth 2/7/2018
有一个对 的调用,该调用发生在 的成员初始化开始时。这与抽象性无关,只是直接拥有成员,只是间接地通过Prototype::Prototype()ConcreteClonable1PrototypeConcreteClonable1Prototype