クラスオブジェクトをキャストしてオブジェクトを構築するC / C ++

Nov 27 2020

CとC ++の2つのプロジェクトがあり、C ++のクラスオブジェクトをCの構造オブジェクトにキャストしようとしています。たとえば、次のようにmyStruにキャストしようとしているmyClassのオブジェクトがあります。

私のC ++プロジェクトには、次のクラスがあります。

class myClass{
    myClass();
    ~myClass();
    char    *data;
    int     var;
}

私のCプロジェクトでは、次の構造になっています。

struct myStru {
    char  *data;
    int    var;
};
typedef struct myStru myStru;

今私のC ++プロジェクトで私はからオブジェクトを作成しますmyClass

myClass *classObj = new myClass();
classObj->data = new char[10];
classObj->var  = 99;

私のCプロジェクトではclassObj、voidポインターとして受け取り、次のようにキャストしようとしています。

myStru *struObj = (myStru*)malloc(sizeof(struct myStru));
struObj = (myStru*) classObj;
printf(" struObj->var %d \n", struObj->var); // this print 99

これは後でC ++プロジェクトで行います

   delete []classObj->data; // I know smart pointers can be used here but this is not my point in this question now
    delete  classObj;

私がここでやっていることは正しいですか?つまり、そのようにキャストclassObjstruObjますか?

完全な例はここにあります(@Borgleaderに感謝) http://coliru.stacked-crooked.com/a/05543b944ee23f2f

編集:私はこの記事で私の質問に対する良い答えを見つけました(CからのC ++クラスへのアクセスを参照): https://www.oracle.com/technical-resources/articles/it-infrastructure/mixing-c-and-cplusplus.html

回答

3 BartekBanachewicz Nov 27 2020 at 13:22

C ++であり、決してそうなることはないので、100%確信はありませんが、これは未定義の動作だと思います。

別の構造体へのメンバーへのポインターを介して、構造体のメンバーにアクセスすることはできません。このルールの注目すべき例外は、共用体のメンバーである2つの構造体の共通の初期シーケンスにアクセスすることです。

代わりに、実際に構造体からクラスを継承した場合、これは機能する可能性があります。

あるいは、他の例外は、そのmemcpyような構造体、AFAIRの間で安全にできることです。

1 Persixty Nov 27 2020 at 17:08

この質問は相互運用性に関するものであり、CおよびC ++コンパイラの実装定義の側面に依存しているため、決定的な答えは得られません。structおよびclassC ++の用語でレイアウト互換型です。1つのaclassと1つのaを宣言structすることが問題ではなく、両方が同じメンバーアクセスを持っているため(互いに異なりますが)互換性があることは非常に明白です(少なくともC ++ 14以降では私は信じています) 。

標準が提供しようとしている最高のものは次のとおりです。

注:標準レイアウトクラスは、他のプログラミング言語で記述されたコードとの通信に役立ちます。それらのレイアウトは12.2で指定されています。—エンドノート

意図は、(標準的なレイアウトおよびレイアウトと互換性の両方である)このようなクラスは、相互に動作可能であることです。同じコンパイラを2つのモードで使用している場合、これが機能しなければ「がっかりする」でしょう。しかし、それはあなたが「がっかりする」ことになる最高のものです-ドキュメントをチェックしてください。

全体的な戦略におけるリソース管理について少し疑問に思います。C ++でデストラクタを宣言しましたが、classそれは問題ありませんvirtual!)がstruct、Cコードにオブジェクトを破棄する「デストラクタのような」関数がある場合は、C側のにコピーします。 'C ++オブジェクトのクローンを作成しました(うまくいけば!)。

Cfree(s->data)が使用したC ++で構築されたオブジェクトのコピーを呼び出した場合、new未定義の振る舞いを引き起こしています。これはmalloc()、互換性のためにC ++側で使用する必要がある場合を除いて可能性があります。

したがって、おそらく問題はありませんが、CとC ++の間の相互運用性機能に依存しており、2つの標準では可能な限り機能しますが、定義上、実装定義の機能を使用しています。

そのメモによって、標準がそれを機能させることをいとわないことを私たちは知っています、そしてそれはおそらくそうするでしょう。幸運を!