2008-11-12 89 views
8

有關C和C++編碼標準的最佳實踐是什麼?是否允許開發人員將它們混合在一起。鏈接C和C++對象文件時是否有任何複雜性。C和C++編碼標準

傳統上用C編寫的套接字庫應該保留在C中並保存在獨立的源文件中嗎?這就是保存.c文件和C++代碼在.cpp文件中的c代碼。 在使用g ++進行語法分析之後混合使用c和C++時,會有任何性能損失,因爲類型安全檢查不在C中完成?但在C++中。將是鏈接C和C++源代碼文件的最佳方式。

回答

7

最大的問題是從C++代碼調用C函數,反之亦然。在這種情況下,您需要確保使用extern "C"將該功能標記爲「C」連接。您可以直接使用頭文件做到這一點:

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

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

#if defined(__cplusplus) 
} 
#endif 

您需要#if是因爲,包括它不會明白extern "C" C代碼。

如果你不想(或不能)改變頭文件,你可以在C++代碼做到這一點:

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

您可以標記一個C++函數具有C鏈接相同方式,然後你可以從C代碼中調用它。你不能爲重載函數或C++類做到這一點。

除此之外,混合C和C++應該沒有問題。我們有許多數十年的C函數,它們仍然被我們的C++代碼使用。

3

C++在運行時不會執行「類型安全檢查」,除非您要求(使用dynamic_cast)。 C++與C高度兼容,因此您可以隨意調用C庫並使用C++編譯器編譯C代碼。 C++並不意味着「面向對象」,並且你不應該因使用它而受到性能損失。

如果您將使用gcc編譯的代碼與g ++混合使用,請參閱Graeme的答案。

+0

只是一個細節,但C++編譯器編譯C有一個內置的C編譯器。 C和C++有不同之處。 – tloach 2008-11-12 13:01:26

0

如果你用g ++編譯你所有的源代碼,那麼它全部用C++對象文件編譯(即用適當的名稱修飾和C++ ABI)。

如果您正在構建需要使用C ABI的顯式C應用程序所使用的庫,則只需使用extern「C」技巧。

如果一切都被編譯成一個可執行文件,然後使用g ++以及如果在C++這就要求在C函數依次調用C++其他功能的功能對待一切,因爲C++

1

,這以後函數拋出一個應該被第一個函數捕獲的異常,除非您告訴C編譯器啓用異常處理表的生成,否則您可能會遇到問題。

海灣合作委員會,這是-fexceptions參數,默認情況下爲C++啓用,但默認C.

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); } 
}; 

我希望這有助於。

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; 
    } 
}