2008-11-12 7 views
8

Was sind Best Practices in Bezug auf C- und C++ - Codierungsstandards? Sollten die Entwickler es schaffen, sie zusammen zu mischen? Gibt es Komplikationen beim Verknüpfen von C- und C++ - Objektdateien?C- und C++ - Codierungsstandards

Sollten Dinge wie Socket-Bibliotheken, die traditionell in C geschrieben sind, in C bleiben und in separaten Quelldateien gespeichert werden? Das hält C-Code in .c-Dateien und C++ - Code in CPP-Dateien. Beim Mischen von C und C++ nach dem Parsen mit g ++ kommt es zu Leistungseinbußen, da in C keine typsicheren Prüfungen durchgeführt werden? aber sind in C++. Wäre der beste Weg, um C- und C++ - Quellcode-Dateien zu verknüpfen.

Antwort

7

Das größte Problem ist das Aufrufen einer C-Funktion aus C++ - Code oder umgekehrt. In diesem Fall möchten Sie sicherstellen, dass Sie die Funktion mit "C" verknüpfen, indem Sie extern "C" verwenden. Sie können diese Datei im Header tun direkt mit:

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

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

#if defined(__cplusplus) 
} 
#endif 

Sie müssen die #if liegt daran, dass C-Code, der es nicht extern "C" verstehen enthält.

Wenn Sie nicht wollen (oder können) die Header-Datei ändern, können Sie es in dem C++ Code tun:

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

Sie können C-Bindung als mit dem gleichen einer C++ Funktion markieren Weg, und dann können Sie es aus C-Code aufrufen. Sie können dies nicht für überladene Funktionen oder C++ - Klassen tun.

Abgesehen davon sollte es kein Problem geben, C und C++ zu mischen. Wir haben eine Reihe von jahrzehntealten C-Funktionen, die immer noch von unserem C++ - Code verwendet werden.

3

C++ führt zur Laufzeit keine 'typsicheren Prüfungen' durch, es sei denn, Sie fragen danach (unter Verwendung von dynamic_cast). C++ ist sehr kompatibel mit C, so dass Sie beliebig C-Bibliotheken aufrufen und C-Code mit einem C++ - Compiler kompilieren können. C++ impliziert nicht "objektorientiert", und Sie sollten keine Leistungseinbußen bei der Verwendung davon bekommen.

Wenn Sie Code mischen, der mit gcc und mit g ++ kompiliert wurde, lesen Sie Graeme's Antwort.

+0

Nur ein Detail, aber ein C++ - Compiler wird C mit einem eingebauten C-Compiler kompilieren. Es gibt ein paar Dinge, die C anders als C++ macht. – tloach

+0

Oh ja. Ich denke jedoch, dass das OP auf strukturierten Code im Aufrufsfunktionsstil als "C-Code" verweist, und mein Punkt war, dass dieser Stil auch "C++ Code" ist; Da es keine Nachteile für die Verwendung von C++ gibt, sollte man sich auch keine Gedanken über den Unterschied machen und alles in C++ machen (nicht unbedingt OOP!). – Sunlight

0

Wenn Sie alle Ihre Quelle mit g ++ kompilieren, dann wird alles in C++ - Objektdateien kompiliert (d. H. Mit dem entsprechenden Namen mangling und dem C++ ABI).

Sie müssen nur den externen "C" -Trick verwenden, wenn Sie Bibliotheken erstellen, die von explizit C-Anwendungen verwendet werden müssen, die den C ABI verwenden müssen.

Wenn alles in einer einzigen ausführbaren dann g ++ und behandeln alles wie C++

1

Wenn Sie eine Funktion in C++ haben, die eine Funktion in C-Aufrufe, die wiederum ruft eine andere Funktion in C++, und diese später verwenden kompilierten function löst eine Ausnahme aus, die von der ersten Funktion abgefangen werden sollte. Sie können Probleme haben, wenn Sie dem C-Compiler nicht befohlen haben, die Generierung der Ausnahmebehandlungstabellen zu aktivieren.

Für gcc, ist dies die -fexceptions Parameter, die standardmäßig für C++ aktiviert ist aber für C. standardmäßig deaktiviert

1

Es gibt keine gute hart und schnell Regeln hier.

Wenn das Endprodukt immer mit einem C++ main() verknüpft wird, spielt es keine Rolle. Da Sie immer Header erstellen können, die das Richtige tun.

Wenn Sie eine Bibliothek erstellen, die eine C- und C++ - Schnittstelle haben muss, aber Sie den C++ - Linker nicht annehmen können, müssen Sie sicherstellen, dass Sie die C-API sauber von C++ trennen. An diesem Punkt ist es in der Regel sauberer die ganze Arbeit in C zu tun und C++ Klassen-Proxy auf den C.

Zum Beispiel verwenden:

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

Ich hoffe, das hilft.

3

Man sollte allgemein davon ausgehen, dass C++ Ausnahmen auslösen kann, daher sollten die c-Wrapper-Funktionen in Ihrem Block sie fangen und in nette Fehlercodes verwandeln, die der c-Aufrufer verdauen kann.

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