0

http://www.parashift.com/c%2B%2B-faq/cpp-objs-passed-to-c.html

答えは2つの部分に分かれています。私が推測する最初の部分は、コードが終わるまでです。

最初の部分では、作成者がCで記述された関数またはC関数によって呼び出されるC ++関数(以下を参照)のいずれかに「C」リンケージディレクティブ(extern "C")を使用しているため、リンクは問題ありません。 。

extern void c_function(Fred*);  // c function 
extern Fred* cplusplus_callback_function(Fred*);  // c++ function

これは理にかなっています。

次に、Fred *はmain()からc_function()に渡されます[これは、C++オブジェクトをC関数に渡すことについてauthor/ faqが言っていることだと思います]、次にcplusplus_callback_function()[オブジェクトはCからC++ドメインに返されます働き]。

それで最初の質問、私は上記を正しく理解していますか?それで、よくある質問への答えは、オブジェクトの「ポインタを渡す」だけですか?

2番目の質問、コードが私を失った後に作者が説明したこと。彼は突然、ポインターが等しいかどうかの比較、ベースと派生の間のポインター変換などについて話します。彼は何を言おうとしているのですか?c_functionに渡された後のそのポインタは、すべての魔法を失いましたか?派生クラスを指す基本クラスポインタでしたか?C関数よりもC ++関数に渡された場合、より多くのことができますか?

最後の質問ですが、C++コードがextern"C"ディレクティブでラップされているかどうかはわかりません。変更されたのはリンケージだけですが、それ以外は何もありません。C++コードはまだC++ですよね?すべてのコードをC++で記述したが、一部の関数を意図的にextern "C"でラップした場合、何が失われますか?

4

3 に答える 3

1

それで、よくある質問への答えは、オブジェクトの「ポインタを渡す」だけですか?

これにはもう1つあります。それは#ifndef __cplusplus、次のことを行う必要があるということです。

typedef struct Fred Fred;

つまり、前方宣言Fredをaとして宣言します(aとaはデフォルトのアクセス権のみが異なるstructことに注意してください)。structclass

彼は何を言おうとしているのですか?c_functionに渡された後のそのポインタは、すべての魔法を失いましたか?

C ++コンパイラが継承を理解し、比較を行う前にポインタ型を変換すること。対照的に、Cコンパイラには継承の概念がなく、実際には、少なくとも1つがvoid*char*またはである場合を除き、単一のオブジェクトへの異なるタイプのポインタを許可しませんunsigned char*。FAQでわかるように、void*CとC ++のブリッジに直面すると、への変換でさえ微妙です。

Base簡単な解決策は、プログラムのC側にポインターのみを与えることです。つまり、可能であれば、継承を完全に非表示にします。

すべてのコードをC++で記述したが、一部の関数を意図的にextern "C"でラップした場合、何が失われますか?

オーバーロード。同じ名前のCリンケージを持つ2つの関数を持つことはできません。

extern "C" {
    void foo(void);
    void foo(int);
}

不可能である。

于 2012-07-29T13:18:09.480 に答える
0

C ++では、多重継承を使用している場合、派生クラスのポインターをその基本クラスの1つにキャストすると、ポインターシフトが発生する可能性があります。

これを確認する例を次に示します。

#include <stdio.h>

using namespace std;

class Base1
{
private:
   int data1;
};

class Base2
{
private:
   int data2;
};

class Derived : public Base1, public Base2 {};

int main()
{
   Derived *derived_pointer = new Derived();
   Base1 *base1_pointer = dynamic_cast< Base1* >( derived_pointer );
   Base2 *base2_pointer = dynamic_cast< Base2* >( derived_pointer );

   printf( "derived = %p\n", derived_pointer );
   printf( "base1 = %p\n", base1_pointer );
   printf( "base2 = %p\n", base2_pointer );

   printf( "dervied == base1_pointer = %d\n", derived_pointer == base1_pointer );
   printf( "derived == base2_pointer = %d\n", derived_pointer == base2_pointer );

   return 0;
}

私のシステム(g ++ 4.6.3でコンパイル)の出力は次のとおりです。

derived = 0x9901008
base1 = 0x9901008
base2 = 0x990100c
dervied == base1_pointer = 1
derived == base2_pointer = 1

ここでは、基本クラスへのポインターが異なっていても、ポインターの比較では、両方が親であるクラスのオブジェクトを指しているため、ポインターが等しいことがわかります。ACプログラムは、継承クラスと基本クラスについて何も知らないため、メモリ内のアドレスを比較するだけです。

于 2012-07-29T13:32:16.983 に答える
0

質問の最初の部分では、c_functionはtypedef structFredFredのポインターを受け取ります。オブジェクトや構造ではありません。では、オブジェクトはそこでどのように使用できますか?このC関数でFred.a_の値をどのように受け取ることができますか?c_function内のa_をマップするように定義できますか?

参照: https ://isocpp.org/wiki/faq/mixing-c-and-cpp#cpp-objs-passed-to-c

于 2016-10-23T17:49:29.523 に答える