rzutowanie obiektu klasy na obiekt struktury C / C ++
Mam dwa projekty, jeden w C, a drugi w C ++ i próbuję rzutować obiekt klasy w C ++ na obiekt struktury w C. Na przykład mam obiekt z myClass, który próbuję rzutować na myStru w następujący sposób:
W moim projekcie C ++ mam taką klasę:
class myClass{
myClass();
~myClass();
char *data;
int var;
}
W moim projekcie C mam taką strukturę:
struct myStru {
char *data;
int var;
};
typedef struct myStru myStru;
Teraz w moim projekcie C ++ tworzę obiekt z myClass
:
myClass *classObj = new myClass();
classObj->data = new char[10];
classObj->var = 99;
W moim projekcie C otrzymuję classObj
jako void pointer i próbuję rzucić go w następujący sposób:
myStru *struObj = (myStru*)malloc(sizeof(struct myStru));
struObj = (myStru*) classObj;
printf(" struObj->var %d \n", struObj->var); // this print 99
Robię to później w moim projekcie C ++
delete []classObj->data; // I know smart pointers can be used here but this is not my point in this question now
delete classObj;
Czy to, co tu robię, jest właściwe? tj. przesyłanie classObj
do struObj
w ten sposób?
Pełny przykład można znaleźć tutaj (dzięki @Borgleader) http://coliru.stacked-crooked.com/a/05543b944ee23f2f
EDYCJA: znalazłem dobrą odpowiedź na moje pytanie w tym artykule (zobacz Dostęp do klas C ++ z C): https://www.oracle.com/technical-resources/articles/it-infrastructure/mixing-c-and-cplusplus.html
Odpowiedzi
Nie jestem w 100% pewien, ponieważ to C ++ i nigdy nie możesz być, ale myślę, że jest to niezdefiniowane zachowanie.
Nie możesz uzyskać dostępu do elementów członkowskich struktury za pośrednictwem wskaźnika do elementu członkowskiego innej struktury. Godnym uwagi wyjątkiem od tej reguły jest dostęp do wspólnej początkowej sekwencji dwóch struktur, które są członkami unii.
To mogłoby zadziałać, gdybyś zamiast tego odziedziczył klasę ze struktury.
Alternatywnie, innym wyjątkiem jest to, że możesz bezpiecznie memcpy
między takimi strukturami, AFAIR.
To pytanie dotyczy współdziałania i nigdy nie uzyskasz ostatecznej odpowiedzi, ponieważ opiera się ono na zdefiniowanych w implementacji aspektach kompilatora C i C ++. struct
I class
są kompatybilne układ typy w kategoriach C ++. Jest bardzo jasne, że zadeklarowanie jednego a class
i jednego a struct
nie stanowi problemu, a ponieważ obaj mają ten sam dostęp do członków dla wszystkich swoich członków (choć różnią się od siebie), są kompatybilne (przynajmniej w C ++ 14) .
Najlepszy standard, jaki ma do zaoferowania, to:
Uwaga: Klasy układu standardowego są przydatne do komunikacji z kodem napisanym w innych językach programowania. Ich układ określono w 12.2. - uwaga końcowa
Intencją jest to, że takie zajęcia (które są zarówno standardowe-układ i układ zgodny) być interoperacyjnych. Jeśli używasz tego samego kompilatora w dwóch trybach, byłoby to „rozczarowujące”, gdyby to nie zadziałało. Ale to najlepsze, co możesz „rozczarować” - sprawdź dokumentację.
Zastanawiam się trochę nad zarządzaniem zasobami w ogólnej strategii. Zadeklarowałeś destruktor w C ++ class
i to w porządku, nie jest virtual
!), Ale kopiujesz go do a struct
po stronie C, jeśli kod C ma funkcję `` destruktora podobnego '' do niszczenia swoich obiektów, co może prowadzić do problemów, ponieważ sklonowałem obiekt w języku C ++ (miejmy nadzieję!).
Jeśli C wywoła free(s->data)
swoją kopię obiektu skonstruowanego w C ++, który używał new
, wywołujesz niezdefiniowane zachowanie. Może to być wyjątek, który gwarantuje użycie malloc()
po stronie C ++ w celu zapewnienia zgodności.
Więc prawdopodobnie jest w porządku, ale polegasz na możliwościach współdziałania między C i C ++, a te dwa standardy prowadzą Cię tak daleko, jak to możliwe, ale z definicji używasz funkcji zdefiniowanych w implementacji.
Dzięki tej notatce wiemy, że standard jest skłonny do działania i prawdopodobnie tak się stanie. Powodzenia!