Por que precisamos colocar membros privados em cabeçalhos?


62

Variáveis ​​privadas são uma maneira de ocultar detalhes de complexidade e implementação para o usuário de uma classe. Este é um recurso bastante interessante. Mas eu não entendo porque no c ++ precisamos colocá-los no cabeçalho de uma classe. Vejo duas desvantagens irritantes para isso:

  • Desordena o cabeçalho do usuário
  • Força a recompilação de todas as bibliotecas clientes sempre que os internos são modificados

Existe uma razão conceitual por trás desse requisito? É apenas para facilitar o trabalho do compilador?


você pode declarar uma estrutura vazia no cabeçalho, mas então você só pode usar ponteiros para tal struct quando você usá-lo (e você não pode alocar um)
catraca aberração

3
@ratchetfreak: Não, vazio ( struct foo{};) não é permitido, mas declarações avançadas ( struct foo;) são.
MSalters

@MSalters é isso que eu quis dizer
catraca aberração

11
Deixe-me acrescentar uma desvantagem: * Escrever cabeçalhos de funções privadas no arquivo .h é uma enorme perda de tempo. (esquecendo as aulas de amigos por um momento)
Jonny

Respostas:


68

Isso ocorre porque o compilador C ++ deve saber o tamanho real da classe para alocar a quantidade certa de memória na instanciação. E o tamanho inclui todos os membros, também privados.

Uma maneira de evitar isso é usar o idioma Pimpl , explicado por Herb Sutter em sua série Guru da Semana # 24 e # 28 .

Atualizar

De fato, isso (ou mais geralmente, a ( #includes) distinção ( ões) do cabeçalho / arquivo de origem é um grande obstáculo no C ++, herdado de C. Na época em que o C ++ C foi criado, ainda não havia experiência com o desenvolvimento de software em larga escala. começa a causar problemas reais. As lições aprendidas desde então foram ouvidas pelos designers de linguagens mais recentes, mas o C ++ está vinculado a requisitos de compatibilidade com versões anteriores, tornando muito difícil abordar uma questão tão fundamental na linguagem.


Esse tipo de informação não está apenas contido na biblioteca de classes? É usado para vincular?
#

@ Simon, o que você quer dizer com "biblioteca de classes"?
Péter Török

Quero dizer a coleção de arquivos objeto que contém a definição e métodos de classe
Simon Bergot

7
Quando o C ++ foi criado, a AT & T / Bell Labs (empregadora da Stroustrups na época) certamente possuía experiência no desenvolvimento de C em larga escala. Seu software de troca de telefone 5ESS era, na época, provavelmente o maior programa C individual do mundo. As primeiras idéias sobre OO já são visíveis nessa base de código, e o Cfront imitou essas técnicas. No entanto, a noção de privateé mais moderna.
MSalters

11
Em C, você simplesmente colocaria o alocador em uma função de biblioteca; o cliente não seria capaz de alocar essa estrutura. Isso aumenta um pouco a sobrecarga, mas torna a migração do código entre as versões trivial, por isso geralmente vale a pena. No entanto, ele tende a levar a um estilo de código muito diferente daquele observado no C ++.
Donal Fellows

15

A definição da classe precisa ser suficiente para o compilador produzir um layout idêntico na memória, sempre que você tiver usado um objeto da classe. Por exemplo, considerando algo como:

class X { 
    int a;
public:
    int b;
};

O compilador normalmente terá ano deslocamento 0 e bno deslocamento 4. Se o compilador viu isso como justo:

class X { 
public:
    int b;
};

Ele "pensaria" que bdeveria estar no deslocamento 0 em vez do deslocamento 4. Quando o código usando essa definição atribuída a b, o código usando a primeira definição seria amodificado e vice-versa.

A maneira usual de minimizar os efeitos de fazer alterações nas partes privadas da classe é geralmente chamada de idioma pimpl (sobre o qual tenho certeza que o Google pode fornecer uma grande quantidade de informações).


11
Estou perguntando sobre uma decisão de design. É claro que você precisaria colocar a declaração de membro particular em algum lugar para o idioma funcionar. Mas por que deveria estar no cabeçalho e não em um local mais privado?
Simon Bergot

7
@ Simon: O cabeçalho é tudo o que o compilador vê para dizer como é a classe / estrutura. Houve discussões sobre a adição de algo como módulos ao C ++, o que ocultaria esse tipo de dados um pouco mais, mas até agora não foi aprovado (embora também não tenha sido totalmente descartado).
21712 Jerry Coffin

3
Ainda assim, uma regra trivial seria alocar esses membros privados "definidos por .cpp" por último. Isso significa que as compensações dos membros públicos e privados "normais" não dependeriam deles. Na IMO, o verdadeiro motivo é que você não pode herdar dessa classe, pois a parte derivada precisa seguir até mesmo os membros privados.
MSalters

3

Provavelmente, existem várias razões. Embora os membros privados não possam ser acessados ​​pela maioria das outras classes, eles ainda podem ser acessados ​​pelas classes de amigos. Portanto, pelo menos nesse caso, eles podem ser necessários no cabeçalho, para que a classe amiga veja que eles existem.

A recompilação de arquivos dependentes pode depender da sua estrutura de inclusão. A inclusão dos arquivos .h em um arquivo .cpp em vez de outro cabeçalho pode, em alguns casos, impedir longas cadeias de recompilações.

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.