Скопировать объект - сохранить полиморфизм - PullRequest
6 голосов
/ 08 ноября 2010

Следующий код пытается скопировать объект и сохранить исходный тип. К сожалению, это не работает (каждый скопированный объект станет 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!

Ответы [ 4 ]

13 голосов
/ 08 ноября 2010

Попробуйте это:

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 (), которую специальная (и любая другая производная от 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.Это научит меня быстро печатать.

РЕДАКТИРОВАТЬ 2: Еще одно исправление.

РЕДАКТИРОВАТЬ3: Я действительно не должен публиковать так быстро, когда в середине работы.Измененный тип возвращаемого значения Special :: clone () для ковариантных типов возвращаемого значения.

4 голосов
/ 08 ноября 2010

Это то, что вам нужно:

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();
}

В одном из предыдущих примеров клон для производного класса неверен.Выше приведен правильный способ реализации метода клонирования.

3 голосов
/ 08 ноября 2010

Только для справки, это в C ++ FAQ:

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

3 голосов
/ 08 ноября 2010

То, что вы хотите, обычно реализуется с использованием абстрактного метода clone в базовом классе.Special обычно реализует этот метод, возвращая new Special(*this).

Также обратите внимание, что рекомендуется делать базовые классы не копируемыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...