【问题标题】:Copy object - keep polymorphism复制对象 - 保持多态性
【发布时间】:2011-05-06 14:03:52
【问题描述】:

以下代码尝试复制对象并保留原始类型。 不幸的是,它不起作用(每个复制的对象都将成为Super,而不是与其原始对象属于同一类)。

请注意copySuper(const Super& givenSuper) 不应该知道Super 的子类。

可以做这样的副本吗?还是我必须更改copySuper 的定义?

#include <string>
#include <iostream>

class Super
{
public:
    Super() {};
    virtual ~Super() {};

    virtual std::string toString() const
    {
        return "I'm Super!";
    }
};

class Special : public Super
{
public:
    Special() {};
    virtual ~Special() {};

    virtual std::string toString() const
    {
        return "I'm Special!";
    }
};

Super* copySuper(const Super& givenSuper)
{
    Super* superCopy( new Super(givenSuper) );
    return superCopy;
}

int main()
{
    Special special;
    std::cout << special.toString() << std::endl;

    std::cout << "---" << std::endl;

    Super* specialCopy = copySuper(special);
    std::cout << specialCopy->toString() << std::endl;

    return 0;
}

//Desired Output:
// # I'm Special!
// # ---
// # I'm Special!
//
//Actual Output:
// # I'm Sepcial!
// # ---
// # I'm Super!

【问题讨论】:

标签: c++ inheritance pointers polymorphism


【解决方案1】:

试试这个:

class Super
{
public:
    Super();// regular ctor
    Super(const Super& _rhs); // copy constructor
    virtual Super* clone() const {return(new Super(*this));};
}; // eo class Super


class Special : public Super
{
public:
    Special() : Super() {};
    Special(const Special& _rhs) : Super(_rhs){};
    virtual Special* clone() const {return(new Special(*this));};
}; // eo class Special

请注意,我们已经实现了一个 clone() 函数,Special(以及 Super 的任何其他派生词)覆盖该函数以创建正确的副本。

例如:

Super* s = new Super();
Super* s2 = s->clone(); // copy of s
Special* a = new Special();
Special* b = a->clone(); // copy of a

编辑:正如其他评论员指出的那样,*this,而不是this。这会教我快速打字。

EDIT2:另一个更正。

EDIT3:我真的不应该在工作中这么快发帖。为协变返回类型修改了 Special::clone() 的返回类型。

【讨论】:

  • 正是我要说的...+1
  • @Moo:同时更正这一行。特殊* b = b->clone(); // a 的副本应该是 a->clone();
  • 还有一件事。您的代码将无法编译,因为这行 'Super();/ regular ctor'
  • 恐怕我不能为此承担责任。我有时会向编辑发誓,因为这在发布时是正确的。无论如何,感谢您指出这一点。
  • +1,虽然我会将复制构造函数和赋值运算符作为protected 放在每个对象中,因为它们的无意使用可能会导致对象切片。我还要注意 return 是一个关键字而不是一个函数,有几个额外的括号我们可以不用。
【解决方案2】:

这就是你需要的:

class Super
{
    public:
        Super()
        {
        }

        virtual Super* clone() const
        {
            return( new Super(*this) );
        };
};


class Special : public Super
{
    public:
        Special() : Super()
        {
        };
        Special(const Special& _rhs) : Super(_rhs)
        {
        };
        virtual Special* clone() const
        {
            return( new Special( *this ) );
        };
};

int main()
{
    Special a;
    Super &c( a );
    Super *b1 = c.clone();
    Special *b2 = a.clone();
    Super *b3 = a.clone();
}

之前的一个例子中派生类的克隆错误。以上是clone方法的正确实现方式。

【讨论】:

  • @Moo-Juice Your Special::clone() 方法返回 Super*,这是错误的。 Special::clone() 的正确返回是 Special*
  • 这绝对会教我仓促发帖,非常感谢。我已经更正了我的帖子。
【解决方案3】:

您想要的通常是使用基类中的抽象clone 方法来实现的。 Special 通常会通过返回new Special(*this) 来实现这个方法。

另请注意,使基类不可复制被认为是最佳实践。

【讨论】:

    【解决方案4】:

    仅作记录,这在 C++ 常见问题解答中:

    http://www.dietmar-kuehl.de/mirror/c++-faq/abcs.html#faq-22.5

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-06
      • 2018-07-08
      相关资源
      最近更新 更多