Вопрос по c++ – C ++: Могут ли работать полиморфные конструкторы копирования?

6

Рассматривать:

<code>class A
{
public:
    A( int val ) : m_ValA( val ) {}
    A( const A& rhs ) {}
    int m_ValA;
};

class B : public A
{
public:
    B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
    B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
    int m_ValB;
};

int main()
{
    A* b1 = new B( 1, 2 );
    A* b2 = new A( *b1 ); // ERROR...but what if it could work?
    return 0;
}
</code>

Будет ли C ++ поврежден, если & quot; new A (b1 )" was able to resolve to creating a new B copy and returning an A?

Будет ли это даже полезно?

Ваш Ответ

6   ответов
1

Выражение

new A(*b1)

уже имеет значение, предполагая, что вы имели соответствующую перегрузку.

Если ему было дано другое значение, вы должны были бы предоставить другой способ получить другое значение. Это бессмысленно, учитывая, что уже есть способ получить то значение, которое вы хотите:

new B(*b1)

И угадайте, что яснее читать.

@ user470379 - абсолютно; моя точка зрения была не в этомnew B(*b1) ответ, это было то, чтоnew A(*b1) не может быть ответом.
Но второй пример предполагает, что вы знаете, априори, чтоb1 на самом делеB.
0

Чтобы ответить на ваш вопрос, еслиnew A( *b1 ) вернул новый экземпляр B, тогда это не будет работать.

int main()
{
    A* b1 = new B( 1, 2 );
    A a( *b1 ); // What size would 'a' be if it was polymorphicly constructed?
    return 0;
}
4

конструктор виртуальных копийи то, что опубликовал eduffy, является стандартным способом сделать это.

Это такжеумные способы сделать это с помощью шаблонов, (отказ от ответственности: самореклама)

Спасибо за вторую ссылку, мне нравится эта концепция.
2

Вместо

class B : public A {
  ...
  A *Clone() { return new B(*this); } 
  ...

};

Вы можете объявить это так:

class B : public A {
  ...
  B *Clone() { return new B(*this); } // note: returning B *
  ...

};

Это все еще считается действительным переопределением виртуальногоA::Clone(); и лучше, если позвонить напрямую черезB *

Круто, но я не понимаю, почему это так? ^^
Потому что это ковариантные типы возврата. & # XA7; 10.3.7
20

Если вам нужно сделать это, общая идиома состоит в том, чтобы иметьClone метод:

class A
{
public:
    A( int val ) : m_ValA( val ) {}
    A( const A& rhs ) {}
    virtual A *Clone () = 0;
    int m_ValA;
};

class B : public A
{
public:
    B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
    B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
    A *Clone() { return new B(*this); }
    int m_ValB;
};

int main()
{
    A* b1 = new B( 1, 2 );
    A* b2 = b1->Clone();
    return 0;
}
Ковариантный возврат лучше: B * B :: Clone ()
Это был действительно мысленный эксперимент. И хотя это стандартный способ реализации конструкторов виртуальных копий, мне было любопытно, почему язык не предоставляет стандартизированного способа сделать это. 0xC0DEFACE
+1, но я бы также добавил виртуальный деструктор в класс;)
0

Существует несколько способов реализации клонирования (например, более или менее стандартный метод clone (), параметризованные варианты объектных фабрик с настраиваемым внедрением зависимостей или без него) без изменения значения существующих программ или невозможности создания экземпляров базовые классы, когда производный класс известен в модуле компиляции.

Конструкторы и деструкторы достаточно сложны для понимания новичками как есть. Вводить в них еще большую сложность было бы неразумно.

Похожие вопросы