lançar objeto de classe para objeto de estrutura C / C ++
Tenho dois projetos, um em C e o outro em C ++, e tento converter um objeto de classe em C ++ para um objeto de estrutura em C. Por exemplo, tenho um objeto de myClass que estou tentando converter em myStru da seguinte maneira:
Em meu projeto C ++, tenho esta classe:
class myClass{
myClass();
~myClass();
char *data;
int var;
}
No meu projeto C, tenho esta estrutura:
struct myStru {
char *data;
int var;
};
typedef struct myStru myStru;
Agora, em meu projeto C ++, crio um objeto a partir de myClass
:
myClass *classObj = new myClass();
classObj->data = new char[10];
classObj->var = 99;
No meu projeto C, recebo classObj
como um ponteiro vazio e tento lançá-lo da seguinte maneira:
myStru *struObj = (myStru*)malloc(sizeof(struct myStru));
struObj = (myStru*) classObj;
printf(" struObj->var %d \n", struObj->var); // this print 99
Eu faço isso mais tarde no meu projeto C ++
delete []classObj->data; // I know smart pointers can be used here but this is not my point in this question now
delete classObj;
O que estou fazendo aqui está certo? ou seja, lançar classObj
para struObj
dessa forma?
O exemplo completo pode ser encontrado aqui (obrigado @Borgleader) http://coliru.stacked-crooked.com/a/05543b944ee23f2f
EDIT: Eu encontrei uma boa resposta para minha pergunta neste artigo (consulte Acessando classes C ++ de C): https://www.oracle.com/technical-resources/articles/it-infrastructure/mixing-c-and-cplusplus.html
Respostas
Não tenho 100% de certeza, porque é C ++ e você nunca pode ter, mas acho que esse é um comportamento indefinido.
Você não pode acessar os membros de uma estrutura por meio de um ponteiro para um membro de outra estrutura. Uma notável exceção a essa regra envolve o acesso à sequência inicial comum de duas estruturas que são membros de um sindicato.
Isso pode funcionar se você realmente herdar sua classe da estrutura.
Alternativamente, a outra exceção é que você pode com segurança memcpy
entre essas estruturas, AFAIR.
Esta pergunta é sobre interoperabilidade e você nunca obterá uma resposta definitiva porque ela depende de aspectos definidos pela implementação do compilador C e C ++. O struct
e o class
são tipos compatíveis com layout em termos de C ++. É muito claro que declarar um a class
e um a struct
não é um problema e porque ambos têm o mesmo acesso de membro para todos os seus membros (embora diferentes um do outro) são compatíveis (pelo menos em C ++ 14 em diante, eu acredito) .
O melhor que o padrão vai oferecer é:
Observação: as classes de layout padrão são úteis para a comunicação com o código escrito em outras linguagens de programação. Seu layout é especificado em 12.2. - nota final
A intenção é que tais classes (que são compatíveis com layout padrão e layout) sejam interoperáveis. Se você estiver usando o mesmo compilador em dois modos, seria 'decepcionante' se isso não funcionasse. Mas isso é o melhor que você obterá 'decepcionante' - verifique a documentação.
Eu me pergunto um pouco sobre o gerenciamento de recursos na estratégia geral. Você declarou um destruidor no C ++ class
e tudo bem, não é virtual
!), Mas você o copia para um struct
no lado C, se o código C tiver uma função 'semelhante ao destruidor' para destruir seus objetos, o que pode causar problemas porque clonou bit a bit o objeto C ++ (espero!).
Se C chamou free(s->data)
sua cópia de um objeto construído em C ++ que o usou, new
você está provocando um comportamento indefinido. Esse pode ser o caso, exceto que garante o uso malloc()
do lado C ++ para compatibilidade.
Portanto, provavelmente está tudo bem, mas você está contando com recursos de interoperabilidade entre C e C ++ e os dois padrões levam você o mais longe possível, mas por definição você está usando recursos definidos de implementação.
Por essa nota, sabemos que o padrão está disposto a funcionar e provavelmente funcionará. Boa sorte!