Pergunta

Considere o seguinte:

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

Será que C ++ ser quebrado se "novo A ( b1)" foi capaz de resolver para a criação de uma nova cópia B e retornando um A ?

Será que isso até ser útil?

Foi útil?

Solução

Você precisa desta funcionalidade, ou é apenas um experimento de pensamento?

Se você precisar fazer isso, o idioma comum é ter um método 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;
}

Outras dicas

O que você está realmente procurando é chamado um virtual construtor de cópia , eo que eduffy postada é a maneira padrão de fazê-lo.

Há também maneiras inteligentes de fazê-lo com modelos . (Disclaimer: auto-promoção)

Apenas uma pequena além da resposta por eduffy: Em vez de

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

};

Você pode declará-lo como este:

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

};

É ainda considerado um primordial válida do A::Clone(); virtual e é melhor se for chamado diretamente através B *

A expressão

new A(*b1)

já tem um significado, supondo que você teve a sobrecarga apropriada.

Se foi dado um significado diferente, você teria que fornecer uma outra maneira de obter a outro significado. Este é tipo de inútil, uma vez que já existe uma maneira de obter o que significa que você quer:

new B(*b1)

E acho que é claro para ler.

Sim. Não.

Há uma série de maneiras de implementar clonagem (por exemplo, o método mais ou menos padrão clone (), as variações parametrizados de fábricas de objetos, com ou sem injeção de dependência configurável) sem alterar o significado dos programas existentes, ou tornando impossível criar exemplos de classes de base quando uma classe de derivados é conhecido dentro de uma unidade de compilação.

construtores e destruidores são suficientemente complexas para entender para iniciantes como é. Injetando ainda mais complexidade para eles seria imprudente.

Como indicado acima, há uma série de maneiras de implementar isso.

Para responder a sua pergunta se new A( *b1 ) retornou uma nova instância de B, então isso não iria funcionar.

int main()
{
    A* b1 = new B( 1, 2 );
    A a( *b1 ); // What size would 'a' be if it was polymorphicly constructed?
    return 0;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top