2008-11-12 34 views
8

¿Cuáles son las mejores prácticas con respecto a los estándares de codificación C y C++? ¿Se les debe permitir a los desarrolladores mezclarlos de todos modos? ¿Hay alguna complicación al vincular archivos de objeto C y C++?C y C++ Estándares de codificación

¿Hay cosas como las bibliotecas de socket que tradicionalmente están escritas en C que permanecen en C y se guardan en archivos de origen separados? Eso es mantener código c en archivos .c y código C++ en archivos .cpp. Cuando se mezclan c y C++ después de analizarse con g ++ ¿habrá penalizaciones de rendimiento, ya que las comprobaciones de tipo seguro no se realizan en C? pero están en C++. Sería la mejor manera de vincular los archivos de código fuente de C y C++.

Respuesta

7

El mayor problema es llamar a una función C desde el código C++ o viceversa. En ese caso, debe asegurarse de marcar la función como que tiene un enlace "C" usando extern "C". Puede hacer esto en el archivo de cabecera usando directamente:

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

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

#if defined(__cplusplus) 
} 
#endif 

Se necesita el #if s porque el código C que incluye no va a entender extern "C".

Si no quiere (o no puede) cambiar el archivo de cabecera, puede hacerlo en el código C++:

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

Puede marcar una función de C++ como teniendo C vinculación de la misma manera, y luego puede llamarlo desde el código C. No puede hacer esto para funciones sobrecargadas o clases C++.

Aparte de eso, no debería haber problemas para mezclar C y C++. Tenemos varias funciones C de hace décadas que todavía están siendo utilizadas por nuestro código C++.

3

C++ no hace 'tipos de cheques seguros' en tiempo de ejecución a menos que los solicite (usando dynamic_cast). C++ es altamente compatible con C, por lo que puede llamar libremente a las bibliotecas C como desee y compilar el código C con un compilador C++. C++ no implica 'orientado a objetos', y no debería obtener ninguna penalización de rendimiento por su uso.

Si mezcla el código compilado con gcc y con g ++, consulte la respuesta de Graeme.

+0

Solo un detalle, pero un compilador de C++ compilará C con un compilador de C incorporado. Hay algunas cosas que C hace diferente de C++. – tloach

+0

Oh sí. Creo, sin embargo, que el OP se refiere al código de estilo de funciones estructuradas y llamativas como "código C", y mi punto era que ese estilo también es "código C++"; ya que no hay ninguna penalización para usar C++, uno también podría no preocuparse por la diferencia y hacer todo en C++ (¡no necesariamente OOP!). – Sunlight

0

Si compila toda su fuente con g ++, entonces todo se compila en archivos de objeto C++ (es decir, con el nombre adecuado de manipulación y el C++ ABI).

Solo necesitará usar el truco externo "C" si está creando librerías que necesitan ser usadas por aplicaciones C explícitamente que necesitan usar el C ABI.

Si todo está siendo compilado en un solo ejecutable a continuación, utilizar g ++ y tratar todo como C++

1

Si usted tiene una función en C++ que llama a una función en C que a su vez llama a otra función en C++, y esto más adelante función arroja una excepción que debe ser captada por la primera función, puede tener problemas a menos que le indique al compilador de C que habilite la generación de las tablas de manejo de excepciones.

para GCC, este es el parámetro -fexceptions, que se activa por defecto para C++, pero desactivados por defecto para C.

1

No hay buenas reglas duras y rápidas aquí.

Si el producto final siempre estará vinculado con un C++ main(), entonces realmente no importa. Como siempre puedes crear encabezados que harán lo correcto.

Si está creando una biblioteca que necesita tener una interfaz C y C++, pero no puede suponer el enlazador C++, entonces deberá asegurarse de separar la API C de C++ limpiamente. En este punto, por lo general es más limpio que hacer todo el trabajo en C y utilizar clases de C++ para proxy al C.

Por ejemplo:

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

espero que esto ayude.

3

En general, se debe suponer que C++ puede arrojar excepciones, por lo tanto, las funciones de envoltura C en su bloque deben atraparlas y transformarlas en agradables códigos de error que la persona que llama puede digerir.

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