Um “construtor de objetos” é um nome mais curto para uma “função com o nome` object` retornando o tipo `object`”?


9

Quero dizer, é uma questão de escolher palavras mais do que existe alguma diferença entre a função e a chamada do construtor. A coisa chamada "construtor de um objeto" também pode ser chamada "função com o nome objectretornando tipo object".

Alguém poderia argumentar que o C ++ não permite ter a mesma função e tipo de nome; no entanto, há uma solução alternativa para fazer isso. O C ++ possui um açúcar sintático especial (chamado de construtor) com o qual você pode criar uma função com o objecttipo de retorno de nome object. Então eu acho que um construtor pode ser visto e usado como uma função independente.

Há algumas diferenças semânticas importantes que estou sentindo falta aqui?


1
Observe que o fato de os construtores terem o nome de seu tipo está longe de ser universal: o PHP os chama de __construct, o Object Pascal / Delphi os chama de Create - e eu me lembro que, nesse caso, é apenas uma convenção, e a verdadeira distinção é que eles tenha a palavra-chave "construtor" na frente de sua definição.
IMSoP

Nota: Os construtores em C ++ não retornam nada (e, portanto, não têm nenhum tipo de retorno).
el.pescado

os médicos são meta-métodos, não métodos. você não envia uma mensagem de ctors para uma instância de uma classe, envia-a para a classe - na verdade, para o objeto de classe, que é o metaobjeto da classe. e os médicos definitivamente não são funções, uma vez que têm efeitos colaterais - você obtém um resultado diferente a cada vez.

Respostas:


17

Um construtor é basicamente um método, sim, mas é um método especial.

Por exemplo, em C ++, um construtor não é simplesmente uma função que retorna uma nova instância desse tipo. Se fosse, a herança não funcionaria. Você não poderia chamar os construtores de base, porque eles retornariam uma nova instância também. Você terminaria com uma nova instância de A, que será retornada ao construtor de B, que cria uma nova instância de B, que será retornada ao construtor de C, etc.

Em vez disso, um construtor é mais um método de inicialização chamado automaticamente pelo alocador de instância. Quando você diz "novo" para criar um objeto no heap, ele aloca a memória para o tipo solicitado (usando um alocador de memória, como malloc) e chama o método construtor nele. O compilador possui regras especiais para como e em que ordem esse construtor pode chamar os outros construtores. Por exemplo, em C #, se você não chamar explicitamente um construtor de base, o compilador adicionará uma chamada ao construtor padrão de base.

São essas regras sobre como o compilador manipula os construtores que o diferenciam de "uma função chamada .ctor que retorna uma instância do tipo".


3
Você também não costuma usar newpara construir objetos em C ++, pois ele possui variáveis ​​automáticas.
Quentin

6

Não, um construtor de objecté muito diferente de uma função chamada objecte retornando object. Um construtor não tem nome, mas isso é em grande parte um detalhe técnico. As diferenças mais importantes são que um construtor não tem tipo de retorno e que não pode ser chamado diretamente.

Um construtor não retorna nada porque recebe um bloco de memória e opera nessa memória no local. Pode ajudar se você esquecer o nome "construtor" por um momento e pensar nele como inicializador . O objetivo do construtor não é construir um objeto "do nada". Seu objetivo é inicializar um objeto no local exato da memória onde ele precisa estar.

Se um construtor retornasse um objeto, esse objeto retornado (o valor retornado) teria que morar em algum lugar (provavelmente na pilha) e, ali, ele precisaria ser inicializado de alguma forma - estamos executando um loop aqui.

Isso anda de mãos dadas com o fato de que um construtor nunca pode ser chamado diretamente. Se você tem uma classe objecte usa uma expressão em object()algum lugar, ela não possui a semântica de "chamar o construtor de object". Possui a semântica de "criar um objeto temporário do tipo object". O compilador traduz isso em alocar algum lugar para o temporário morar (provavelmente / geralmente na pilha) e chamar o construtor para construir (= inicializar) um objeto naquele local.

O mesmo princípio se aplica ao usar new object(). Esta é uma nova expressão, que faz duas coisas:

  1. Chame uma função de alocação operator new(que retorna a void*) para alocar memória não processada para o objeto.
  2. Emita uma chamada de construtor nessa memória não processada para construir (= inicializar) um objeto nessa parte da memória não processada.

Pensando em um construtor de objectcomo uma função como esta:

static object object();

está errado. Se alguma coisa, a maneira como um construtor trabalha é mais próxima disso:

static void object(object &place_to_work_in);

Com a exceção de que você nunca pode chamá-lo diretamente. Ele sempre é chamado apenas quando especificado por uma construção de idioma diferente. Mesmo o posicionamento new (também conhecido como o truque "chame um construtor aqui"), new (&place_for_object) object()não chama o construtor diretamente. Ele se traduz em uma chamada para a forma nova colocação, operator newque retorna seu argumento, seguida por uma chamada para o construtor (como qualquer outra nova expressão).


Confesso que não participo muito dessa pilha, por isso talvez não esteja familiarizado com a cultura e os padrões esperados aqui. Se houver algo que eu possa melhorar nessa resposta, informe-me, além de reduzir a votação, para que eu possa corrigi-la.
Angew não está mais orgulhoso de SO

+1 Não se preocupe com o voto negativo, sua resposta é ótima :) Por alguma razão, quase todas as respostas aqui têm um voto negativo.
amon

1

Sua tentativa de reformular está incorreta.

Embora um construtor se pareça com uma função de membro com um nome igual ao nome da classe, o fato é que um construtor realmente não tem um nome. Isso é explicitamente declarado no padrão C ++ (seção [class.ctor] / 1):

Construtores não têm nomes.

Tanto quanto: "Eu acho que um construtor pode ser visto e usado como uma função independente" vai ... bem, eu não tenho muita certeza do que você quer dizer. Uma função livre certamente não pode ser um construtor - um construtor deve ser um membro de uma classe. Ao mesmo tempo, você certamente pode definir uma função livre que cria um objeto e retorna uma instância desse objeto. Essa função livre pode até (mais ou menos) ter o mesmo nome que o tipo de objeto que ela cria, se você desejar o suficiente. Por exemplo, você pode definir a classe dentro de um espaço para nome e, em seguida, definir uma função fora do espaço para nome:

namespace foo { 
    class bar {};
}

foo::bar bar() { return foo::bar(); }

Esse não é realmente o mesmo nome (a função é justa bare a classe é foo::bar), mas, dependendo do seu ponto de vista, você pode vê-los dessa maneira.

Essa função livre não teria as outras características principais de um construtor. A invocação de um construtor pode ser completamente implícita. Por exemplo, se eu tiver uma classe como:

class foo {
public:
   foo (int) {}
   foo operator+(foo const &other) {}
};

... então codifique como:

foo f(1);

foo h(0);
h = f + 1;

... pode criar um objeto foo temporário a partir do qual 1ele pode passar esse objeto foo foo::operator+. Isso simplesmente não acontecerá com uma função livre, mesmo se essa função livre tiver sido definida para pegar o tipo de parâmetro correto e retornar o tipo de resultado necessário. Para uma conversão implícita, é necessário um construtor.


1

Quero dizer, é uma questão de escolher palavras mais do que existe alguma diferença entre a função e a chamada do construtor. A coisa denominada "construtor de um objeto" também pode ser denominada "função com o nome do objeto retornando o tipo de objeto".

Primeiro, os construtores não retornam nada e, como conseqüência, não têm tipos de retorno.

Segundo, os construtores são diferentes, pois você não pode realmente chamar o construtor diretamente de uma maneira que chama funções. Em vez disso, se você declarar uma variável, os construtores apropriados serão chamados pelo tempo de execução.

Terceiro, no caso de herança, funções regulares nas subclasses substituem as funções nas classes pai. Os construtores, por outro lado, construtores de classe pai em cascata são chamados primeiro e, em seguida, subclasse de construtores.

Quarto, os construtores podem ter listas de inicialização, enquanto a função "normal" não pode.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.