Pergunta

Se eu tiver uma classe da seguinte maneira

   class Example_Class 
   {
       private:
         int x; 
         int y; 
       public: 
         Example_Class() 
         { 
             x = 8;
             y = 9;
         }
       ~Example_Class() 
       { } 
   };

E um struct da seguinte maneira

struct
{
   int x;
   int y;
} example_struct;

A estrutura em memória do example_struct simmilar para que em Example_Class

Por exemplo, se eu faço o seguinte

struct example_struct foo_struct;
Example_Class foo_class = Example_Class();

memcpy(&foo_struct, &foo_class, sizeof(foo_struct));

vai foo_struct.x = 8 e foo_struct.y = 9 (ou seja: os mesmos valores que o x, os valores de y no foo_class)?

A razão que eu peço é que eu tenho uma biblioteca C ++ (não quer mudá-lo) que está compartilhando um objeto com código C e eu quero usar um struct para representar o objeto vindo da biblioteca C ++. Eu só estou interessado no atributos do objeto.

Eu sei que a situação ideal seria ter Example_class envoltório arround uma estrutura comum entre o código C e C ++, mas não vai ser fácil mudar a biblioteca C ++ em uso.

Foi útil?

Solução

O padrão C ++ garantias que esquemas de memória de um struct C e C ++ class (ou struct - mesma coisa) será idêntico, desde que o C class ++ / struct se encaixa nos critérios de ser < strong> POD ( "dados de Old Plain"). Então, o que POD significa?

A classe ou struct é POD se:

  • Todos membros de dados são públicos e eles próprios POD ou fundamentais tipos (tipos, mas não de referência ou ponteiro-para-membro), ou matrizes de tais
  • Não tem construtores definidos pelo usuário, operadores de atribuição ou destruidores
  • Não tem funções virtuais
  • Não tem classes base

Sobre o único "C ++ - ismos". Permitidas são funções membro não-virtuais, membros estáticos e funções membro

Desde a sua classe tem tanto um construtor e um destrutor, é formalmente falando não do tipo POD, por isso, a garantia não se sustenta. (Embora, como já foi mencionado, na prática, os dois layouts são susceptíveis de ser idêntica em qualquer compilador que você tente, contanto que não há funções virtuais).

Veja a seção [26,7] do C ++ FAQ Lite para mais detalhes.

Outras dicas

A estrutura em memória do example_struct simmilar para que em Example_Class

O comportamento não é garantido, e é dependente do compilador.

Dito isto, a resposta é "sim, na minha máquina", desde que o Example_Class contém nenhum método virtual (e não herda de uma classe base).

No caso que você descreve, a resposta é "provavelmente sim". No entanto, se a classe tem quaisquer funções virtuais (incluindo destrutor virtual, que pode ser herdada de uma classe base), ou usa herança múltipla em seguida, o layout de classe pode ser diferente.

Para adicionar ao que outras pessoas têm dito (por exemplo: específico do compilador, provavelmente irá trabalhar enquanto você não tem funções virtuais):

Eu altamente sugerir um assert estático (verificação em tempo de compilação) que o sizeof (Example_class) == sizeof (example_struct) se você estiver fazendo isso. Veja BOOST_STATIC_ASSERT, ou o equivalente específico do compilador ou construção personalizada. Esta é uma boa primeira linha de defesa, se alguém (ou alguma coisa, como uma mudança do compilador) modifica a classe para invalidar a partida. Se você quiser verificação extra, você também pode verificar tempo de execução que os deslocamentos para os membros são iguais, que (juntamente com o assert tamanho estática) vai garantir a exatidão.

Nos primeiros dias de compiladores C ++ havia exemplos quando compilador primeiras mudanças struct palavras-chave com classe e, em seguida, compila. Tanto sobre semelhanças.

As diferenças vêm de herança de classe e, sobretudo, funções virtuais. Se classe contém funções virtuais, então ele deve ter um ponteiro para o tipo descritor no início de seu layout. Além disso, se herda da classe B de classe A, em seguida, layout de classe de A vem em primeiro lugar, seguido pelo próprio layout de classe da B.

Assim, a resposta precisa à sua pergunta sobre apenas lançando uma instância de classe a uma instância estrutura é: depende de conteúdo de classe. Para determinada classe que tem métodos (construtor e destruidor não-virtual), o layout é provavelmente vai ser o mesmo. Se o processo de destruição ser declarado virtual, o layout iria se tornar diferente entre estrutura e classe.

Aqui está um artigo que mostra que não há muito precisava fazer para etapa de estruturas C para as classes C ++: Lição 1 - a partir Estrutura de Classe

E aqui está o artigo que explica como funções virtuais mesa é introduzido para classes que têm funções virtuais: Lição 4 - Polimorfismo

Aulas e estruturas em C ++ são o equivalente, exceto que todos os membros de uma struct são públicos por padrão (os membros da classe são privados por padrão). Isso garante que a compilação de código legado C em um compilador C ++ vai funcionar como esperado.

Não há nada que você parar de usar toda a imaginação C ++ apresenta em um struct:

struct ReallyAClass
{
    ReallyAClass();
    virtual !ReallAClass();

    /// etc etc etc
};

Por que não atribuir explicitamente membros da classe para a estrutura é quando você quer passar os dados para C? Dessa forma, você sabe que seu código irá funcionar em qualquer lugar.

Você provavelmente apenas derivar a classe a partir da estrutura, público ou privado. Em seguida, lançando-se resolver corretamente no código C ++.

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