8

C および C++ コーディング標準に関するベスト プラクティスは何ですか? 開発者が勝手にそれらを混ぜ合わせることを許可されるべきか. C と C++ のオブジェクト ファイルをリンクするときに複雑なことはありますか。

伝統的に C で書かれているソケット ライブラリのようなものは、C のままにして、別のソース ファイルに保持する必要がありますか? つまり、c コードを .c ファイルに保持し、c++ コードを .cpp ファイルに保持します。C ではタイプセーフ チェックが行われないため、g++ で解析した後に c と C++ を混合すると、パフォーマンスが低下しますか? ただし、C++ です。C および C++ のソース コード ファイルをリンクするには、これが最適な方法です。

4

6 に答える 6

7

最大の問題は、C++ コードから C 関数を呼び出すこと、またはその逆です。その場合、関数を使用して「C」リンケージを持っていることを確認する必要がありますextern "C"。これは、次を使用してヘッダー ファイルで直接行うことができます。

#if defined( __cplusplus )
extern "C" {
#endif

extern int myfunc( const char *param, int another_one );

#if defined( __cplusplus )
}
#endif

#ifs を含む C コードは理解できないため、s が必要ですextern "C"

ヘッダー ファイルを変更したくない (または変更できない) 場合は、C++ コードで行うことができます。

extern "C" {
#include "myfuncheader.h"
}

同じ方法で C++ 関数を C リンケージを持つものとしてマークし、C コードから呼び出すことができます。オーバーロードされた関数または C++ クラスに対してこれを行うことはできません。

それ以外は、C と C++ を混在させても問題はありません。C++ コードでまだ使用されている数十年前の C 関数が多数あります。

于 2008-11-12T11:53:56.863 に答える
3

一般に、c++ は例外をスローできると想定する必要があります。したがって、ブロック内の c ラッパー関数はそれらをキャッチし、c 呼び出し元が消化できる適切なエラー コードに変換する必要があります。

extern "c"
{
    int nice_c_function_interface
    (
        void
    )
    {
        int returnStatus;

        try
        {
             returnStatus = nice_cpp_function();
        }
        catch (NiceCppException& that)
        {
             returnStatus = that.failure_code();  
        }
        catch (...)
        {
            cerr << "Oh Worse! an unexpected unknown exception" << endl;

            returnStatus = -1;  // Horrible unknown failure
        }

        return returnStatus;
    }
}
于 2008-11-12T19:33:43.020 に答える
3

C++ は、( を使用して) 要求しない限り、実行時に「タイプセーフ チェック」を行いませんdynamic_cast。C++ は C との互換性が高いため、自由に C ライブラリを呼び出して、C++ コンパイラで C コードをコンパイルできます。C++ は「オブジェクト指向」を意味するものではなく、それを使用してもパフォーマンスが低下することはありません。

gcc と g++ でコンパイルされたコードを混在させる場合は、Graeme の回答を参照してください。

于 2008-11-12T11:57:16.497 に答える
1

C++ の関数を呼び出し、C++ の別の関数を呼び出す C++ の関数があり、この後の関数が最初の関数によってキャッチされる例外をスローする場合、C コンパイラに有効にするように指示しない限り、問題が発生する可能性があります。例外処理テーブルの生成。

gcc の場合、これは-fexceptionsパラメーターであり、C++ ではデフォルトで有効になっていますが、C ではデフォルトで無効になっています。

于 2008-11-12T12:34:42.880 に答える
1

ここには、厳格で厳格なルールはありません。

最終製品が常に C++ の main() にリンクされる場合、それは問題ではありません。正しいことを行うヘッダーをいつでも作成できるためです。

C および C++ インターフェイスを必要とするライブラリを作成しているが、C++ リンカを想定できない場合は、C API を C++ から明確に分離する必要があります。この時点で、通常はすべての作業を C で行い、C++ クラスを使用して C にプロキシする方がクリーンです。

例えば:

/* c header */

struct CData
 { /* stuff */ };

void init( CData* data );
void fini( CData* data );
int getSomething( CData* data );
void doSomething( CData* data, int val );

// c++ header

extern "C" {
#include cdata.h
};

class CppData : private CData
 {
 public:
   CppData() { ::init( (CData*)this ); }
   ~CppData() { ::fini( (CData*)this ); }
   int getSomething() { return ::getSomething( (CData*)this ); }
   void doSomething( int val ) { :: doSomething( (CData*)this, val ); }
 };

これが役立つことを願っています。

于 2008-11-12T12:47:45.053 に答える
0

すべてのソースを g++ でコンパイルすると、すべて C++ オブジェクト ファイルにコンパイルされます (つまり、適切な名前マングリングと C++ ABI を使用して)。

C ABI を使用する必要がある明示的な C アプリケーションで使用する必要があるライブラリを構築する場合にのみ、extern "C" トリックを使用する必要があります。

すべてが単一の実行可能ファイルにコンパイルされている場合は、g++ を使用し、すべてを C++ として扱います

于 2008-11-12T12:31:46.490 に答える