Pergunta

Por que o C ++ não tem um construtor virtual?

Nenhuma solução correta

Outras dicas

Ouvi-lo da boca do cavalo :).

De Estilo ++ C de Bjarne Stroustrup e Técnica FAQ Por que não vamos ter construtores virtuais?

Uma chamada virtual é um mecanismo para começar o trabalho feito dado parcial em formação. Em particular, "virtual" nos permite chamar uma função sabendo apenas todas as interfaces e não o tipo exato do objeto. Para criar um objeto que você precisa obter informações completas. Em particular, você precisa saber o tipo exato do que você deseja criar. Consequentemente, uma "chamada para um construtor" não pode ser virtual.

A entrada FAQ passa a dar o código para uma forma de atingir este objectivo sem um construtor virtual.

funções virtuais, basicamente, fornecer o comportamento polimórfico. Isto é, quando você trabalha com um objeto cujo tipo de dinâmica é diferente do tipo estático (tempo de compilação) com o qual é referido, ele fornece um comportamento que é apropriado para o real tipo de objeto em vez de o tipo estático do objeto.

Agora tente aplicar esse tipo de comportamento para um construtor. Quando você construir um objeto do tipo estático é sempre o mesmo que o tipo de objeto real, pois:

Para construir um objeto, um construtor precisa o tipo exato do objeto é criar [...] Além disso [...] você não pode ter um ponteiro para um construtor

(Bjarne Stroustup (P424 A programação C ++ Idioma SE))

orientadas a objeto linguagens Ao contrário, como Smalltalk ou Python, onde o construtor é um método virtual do objeto que representa a classe (o que significa que você não precisa do GoF resumo padrão fábrica , como você pode passar o objeto que representa a classe em torno em vez de fazer o seu próprio), C ++ é uma linguagem de classe base, e não tem objetos que representam qualquer de construções da linguagem. A classe não existe como um objeto em tempo de execução, para que você não pode chamar um método virtual sobre ele.

Isso se encaixa com o 'você não paga para o que você não usa' filosofia, apesar de todo grande projeto C ++ Eu vi acabou implementando alguma forma de fábrica abstrata ou reflexão.

duas razões que eu posso pensar de:

razão técnica

O objeto existe somente após o fim ends.In construtor para o construtor para ser despachado usando a tabela virtual, tem de haver um objeto existente com um ponteiro para a mesa virtual, mas como pode um ponteiro para a exist tabela virtual se o objeto ainda não existe? :)

razão lógica

Você usa a palavra-chave virtual quando você quiser declarar um comportamento um tanto polimórfico. Mas não há nada polimórfico com construtores, trabalho construtores em C ++ é simplesmente colocar um conjunto de dados de objetos na memória. Desde mesas virtuais (e polimorfismo em geral) são todos sobre o comportamento polimórfico vez em dados polimórficos, Não há nenhum sentido com declarar um construtor virtual.

Nós fazemos, não é apenas um construtor: -)

struct A {
  virtual ~A() {}
  virtual A * Clone() { return new A; }
};

struct B : public A {
  virtual A * Clone() { return new B; }
};

int main() {

   A * a1 = new B;
   A * a2 = a1->Clone();    // virtual construction
   delete a2;
   delete a1;
}

razões Semântica à parte, não há vtable até depois que o objeto é construído, tornando assim uma designação virtual inútil.

Resumo : o padrão C ++ poderia especificar uma notação e comportamento para s "construtor virtual", que é razoavelmente intuitiva e não muito difícil para compiladores para apoio, mas por que fazer uma mudança padrão para isso especificamente quando o funcionalidade pode já estar limpa implementado usando create() / clone() (veja abaixo)? Não é quase tão útil como muitos proposta outra língua no pipeline.

Discussão

Vamos postulado um mecanismo de "construtor virtual":

Base* p = new Derived(...);
Base* p2 = new p->Base();  // possible syntax???

No exemplo acima, a primeira linha constrói um objeto Derived, assim tabela de expedição virtual do *p pode razoavelmente fornecer um "construtor virtual" para uso na segunda linha. (Dezenas de respostas nesta página afirmando "o objeto ainda não existe construção tão virtual é impossível" são desnecessariamente míope focada no objeto a-ser-construído.)

A segunda linha postula a new p->Base() notação para alocação e padrão de construção solicitação dinâmica de outro objeto Derived.

Notas:

  • a alocação de memória orquestrar compilador deve antes de chamar o construtor - construtores normalmente apoiar (informalmente "pilha") alocação automática, estática (para o escopo global / namespace e objetos / função-static de aula), e dinâmico (informalmente "pilha") quando new é usado

    • o tamanho do objeto a ser construído por p->Base() geralmente não pode ser conhecido em tempo de compilação, então alocação dinâmica é a única abordagem que faz sentido

  • para alocação dinâmica que deve retornar um ponteiro para que a memória pode ser deleted mais tarde.

  • a notação postulado explicitamente listas new para enfatizar a alocação dinâmica eo tipo ponteiro.

O compilador seria necessário:

  • descobrir quanta memória Derived necessário, quer chamando uma função implícita virtual sizeof ou ter essas informações disponíveis via RTTI
  • chamada operator new(size_t) para alocar memória
  • invoke Derived() com new colocação.

ou

  • criar uma entrada vtable extra para uma função que alocação combina dinâmica e construção

Assim - não parece intransponível para especificar e implementar construtores virtuais, mas a pergunta do milhão de dólares é: como seria melhor do que o que é possível usando ++ recursos de linguagem existentes C ...? Pessoalmente, Não vejo nenhuma vantagem sobre a solução abaixo.


`clone ()` e `create ()`

O C ++ documentos FAQ um "construtor virtual" idioma , contendo virtual create() e clone() métodos para default-construção ou copiar e construir um novo objeto alocada dinamicamente-:

class Shape {
  public:
    virtual ~Shape() { } // A virtual destructor
    virtual void draw() = 0; // A pure virtual function
    virtual void move() = 0;
    // ...
    virtual Shape* clone() const = 0; // Uses the copy constructor
    virtual Shape* create() const = 0; // Uses the default constructor
};
class Circle : public Shape {
  public:
    Circle* clone() const; // Covariant Return Types; see below
    Circle* create() const; // Covariant Return Types; see below
    // ...
};
Circle* Circle::clone() const { return new Circle(*this); }
Circle* Circle::create() const { return new Circle(); }

Também é possível alterar ou create() sobrecarga para aceitar argumentos, embora para coincidir com a assinatura função virtual a classe base / de interface, argumentos para substituições devem corresponder exatamente uma das sobrecargas de classe base. With estas instalações fornecidos pelo usuário explícitas, é fácil adicionar o registo, instrumentação, alocação de memória alter etc ..

Você pode encontrar um exemplo e a razão técnica para por isso que não é permitido em resposta @stefan 's. Agora, uma resposta lógica a esta questão de acordo para mim é:

O principal uso da palavra-chave virtual é permitir que o comportamento polimórfico quando não sabemos que tipo de objeto o ponteiro classe base irá apontar para.

Mas acho que isso é mais primitiva forma, para usar a funcionalidade virtual que você vai exigir um ponteiro. E o que faz um ponteiro exige? Um objeto para apontar para! (Considerando-se caso para a execução correta do programa)

Então, nós, basicamente, exigem um objeto que já existe em algum lugar na memória (não estamos preocupados com a forma como a memória foi alocado, pode ser em tempo de compilação ou seja runtime) para que o nosso ponteiro pode corretamente ponto a esse objeto.

Agora, pense da situação sobre o momento em que o objeto da classe a ser apontado está sendo atribuído alguma memória -> Seu construtor será chamado automaticamente no que se instância

!

Assim, podemos ver que nós realmente não precisa se preocupar com o construtor de ser virtual, porque em qualquer dos casos, você quiser usar um comportamento polimórfico nosso construtor já teria sido executada fazendo nosso objeto pronto para uso

Embora o conceito de construtores virtuais não se encaixa bem desde que tipo de objeto é pré-requisito para a criação do objeto, não é completamente over-governado.

'método de fábrica' padrão de design do GOF faz uso do 'conceito' do construtor virtual, que é handly em determinadas situações de projecto.

funções virtuais em C ++ são uma implementação do polimorfismo em tempo de execução, e eles vão fazer a função primordial. Geralmente a palavra-chave virtual é usado em C ++ quando você precisa de comportamento dinâmico. Ele vai trabalhar somente quando existe objeto. Considerando construtores são usados ??para criar os objetos. Construtores será chamado no momento da criação do objeto.

Então, se você criar o construtor como virtual, conforme a definição de palavra-chave virtual, ele deve ter objeto existente para uso, mas construtor é usado para criar o objeto, de modo que este caso nunca vai existir. Então você não deve usar o construtor como virtual.

Assim, se tentar declarar compilador construtor virtual lançar um erro:

Construtores não podem ser declaradas virtual

Quando as pessoas perguntam uma pergunta como esta, eu gosto de pensar para mim mesmo "o que aconteceria se isso fosse realmente possível?" Eu realmente não sei o que isso significa, mas eu acho que teria algo a ver com ser capaz de substituir a implementação construtor com base no tipo dinâmico do objeto que está sendo criado.

Eu vejo uma série de potenciais problemas com isso. Por um lado, a classe derivada não será totalmente construído na época o construtor virtual é chamado, de forma que há potenciais problemas com a implementação.

Em segundo lugar, o que aconteceria no caso de herança múltipla? Seu construtor virtual seria chamado várias vezes, presumivelmente, você iria em seguida, precisa ter alguma forma de saber qual deles estava sendo chamado.

Em terceiro lugar, de modo geral, no momento da construção, o objeto não tem a tabela virtual totalmente construído, isso significa que exigiria uma grande mudança para a especificação da linguagem para permitir o fato de que o tipo dinâmico do objeto seria conhecido no momento da construção. Este seria, então permitir que o construtor da classe base para talvez chamar outras funções virtuais em tempo de construção, com um tipo de classe dinâmica não totalmente construído.

Finalmente, como alguém apontou que você pode implementar um tipo de construtor virtual usando estático "criar" ou "init" funções do tipo que basicamente fazer a mesma coisa que um construtor virtual faria.

funções virtuais são usados ??para invocar funções com base no tipo de objeto apontado pelo ponteiro, e não o tipo de si ponteiro. Mas um construtor não está "invocado". Ele é chamado apenas uma vez quando um objeto é declarado. Assim, um construtor não pode ser feita virtual em C ++.

Você não deve chamar a função virtual dentro do construtor quer. Veja: http://www.artima.com/cppsource/nevercall.html

Além disso, eu não tenho certeza de que você realmente precisa de um construtor virtual. Você pode conseguir construção polimórfica sem ele:. Você pode escrever uma função que irá construir o seu objeto de acordo com os parâmetros necessários

A-tabela virtual (TabelaV) é feito para cada classe possuindo um ou mais 'virtuais funções'. Quando é criado um objecto de tal classe, que contém um 'virtual-ponteiro' que aponta para a base de TabelaV correspondente. Sempre que há uma chamada de função virtual, o vtable é usado para resolver para o endereço de função. Construtor não pode ser virtual, porque quando construtor de uma classe é executado não há vtable na memória, não significa nenhum ponteiro virtual definido ainda. Daí o construtor deve ser sempre não-virtual.

Cant nós simplesmente dizer que gosto .. Não podemos construtores herdar. Portanto, não há ponto de declará-los virtual porque o virtual fornece polimorfismo.

O mecanismo virtual só funciona quando você tem um ponteiro de classe base de um objeto de classe derivada. Construção tem suas regras próprias para o chamado de construtores de classe de base, classe basicamente base para derivada. Como poderia um construtor virtual ser útil ou chamado? Eu não sei o que as outras línguas fazer, mas eu não posso ver como um construtor virtual poderia ser útil ou mesmo implementadas. necessidades de construção para ter ocorrido para o mecanismo virtual para fazer qualquer sentido e construção também deve ter ocorrido para as estruturas vtable ter sido criado, que fornece a mecânica do comportamento polimórfico.

Há uma razão muito simples:. Construtores são funções efetivamente estáticos, e em C ++ nenhuma função estática pode ser virtual

Se você tem muita experiência com C ++, você sabe tudo sobre a diferença entre funções estáticas e membros. funções estáticas estão associados com a classe, não os objetos (instâncias), para que eles não ver um ponteiro "este". Apenas as funções de membro pode ser virtual, porque o vtable- a mesa escondida de ponteiros de função que faz 'virtual' Work é realmente um membro de dados de cada objeto.

Agora, o que é o trabalho do construtor? É no "T" construtor nome- um inicializa T objetos como eles são alocados. Isso impede automaticamente que seja uma função de membro! Um objeto tem de existir antes que ele tenha um ponteiro "este" e, portanto, uma vtable. Isso significa que, mesmo se os construtores de linguagem tratados como funções comuns (não, por motivos relacionados eu não vou entrar em), eles teriam que ser funções de membro estático.

Uma ótima maneira de ver isso é olhar para o padrão "Factory", especialmente funções de fábrica. Eles fazem o que você está depois, e você vai notar que se a classe T tem um método de fábrica, é sempre estática. Tem que ser.

construtor virtual C ++ não é exemplo possible.For você não pode marcar um construtor como virtual.Try este código

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        virtual aClass()
        {   
        }  
};
int main()
{
    aClass a; 
}

Isso faz com que um código error.This está tentando declarar um construtor como virtual. Agora vamos tentar entender por que usamos palavra-chave virtual. palavra-chave virtual é usado para fornecer polimorfismo tempo de execução. Por exemplo, tentar este código.

#include<iostream.h>
using namespace std;
class aClass
{
    public:
        aClass()
        {
            cout<<"aClass contructor\n";
        }
        ~aClass()
        {
            cout<<"aClass destructor\n";
        }

};
class anotherClass:public aClass
{

    public:
        anotherClass()
        {
            cout<<"anotherClass Constructor\n";
        }
        ~anotherClass()
        {
            cout<<"anotherClass destructor\n";
        }

};
int main()
{
    aClass* a;
    a=new anotherClass;
    delete a;   
    getchar(); 
}

Em principais aloca a=new anotherClass; uma memória para anotherClass em um a ponteiro declarado como tipo de aClass.This faz com que tanto o construtor (Em aClass e anotherClass) para chamar automatically.So não precisamos para o construtor marca como virtual.Because quando um objecto é criado deve seguir a corrente de criação (ou seja, em primeiro lugar a base e, em seguida, as classes de derivados). Mas quando tentamos excluir um delete a; que provoca a chamar apenas a base destructor.So temos de lidar com o processo de destruição usando palavra-chave virtual. construtor Então virtual não é possível, mas destruidor virtual é .graças

Se você pensar logicamente sobre como construtores de trabalho e qual é o significado / uso de uma função virtual é em C ++, então você vai perceber que um construtor virtual seria sem sentido em C ++. Declarando algo virtual no meio C ++ que pode ser substituído por uma sub-classe da classe atual, no entanto, o construtor é chamado quando o objetou é criado, nesse momento você não pode ser a criação de uma sub-classe da classe, você deve ser criar a classe de modo que não haveria qualquer necessidade de declarar um construtor virtual.

E outra razão é, os construtores têm o mesmo nome de seu nome de classe e se declarar construtor como virtual, então ele deve ser redefinido em sua classe derivada com o mesmo nome, mas você não pode ter o mesmo nome de dois Aulas. Portanto, não é possível ter um construtor virtual.

  1. Quando um construtor é invocado, embora não haja nenhum objeto criado até aquele momento, nós ainda não sabemos o tipo de objeto que vai ser criado porque o específica construtor da classe à qual o objeto pertence já foi chamado.

    Virtual palavra-chave associada a um meio de função do função de um determinado tipo de objeto vai ser chamado.

    Então, meu pensamento diz que não há necessidade de fazer o construtor virtual porque já o construtor desejado cujo objeto é vai ser criado foi invocado e fazendo construtor virtual é apenas uma coisa redundante de fazer, porque o object- específica construtor já foi invocado e isso é mesmo que chamar função específica de classe o que é conseguido através da palavra-chave virtual.

    Embora a implementação interna não permitirá construtor virtual para vptr e motivos relacionados vtable.


  1. Outra razão é que C ++ é uma linguagem de tipagem estática e precisamos saber o tipo de uma variável em tempo de compilação.

    O compilador deve estar ciente do tipo de classe para criar o objeto. O tipo de objeto a ser criado é uma decisão em tempo de compilação.

    Se fizermos o construtor virtual, em seguida, isso significa que não precisamos saber o tipo do objeto em tempo de compilação (que é o que função virtual fornecem. Nós não precisamos de saber o objeto real e só precisa do ponteiro de base para apontar um objeto real chamar funções virtuais do objecto pontiagudo sem saber o tipo do objeto) e se não sabemos o tipo de objeto em tempo de compilação, em seguida, é contra as linguagens de tipagem estática. E, portanto, o polimorfismo em tempo de execução não pode ser alcançado.

    Assim, Constructor não será chamado sem saber o tipo do objeto em tempo de compilação. E assim a idéia de fazer um construtor virtual falhar.

O Vpointer é criado no momento da criação do objeto. vpointer costuma existe antes da criação do objeto. por isso não há ponto de fazer o construtor como virtual.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top