C и C ++ Стандарты кодирования - PullRequest
8 голосов
/ 12 ноября 2008

Каковы наилучшие практики в отношении стандартов кодирования C и C ++? Если разработчикам будет позволено смешивать их вместе. Существуют ли какие-либо сложности при связывании объектных файлов C и C ++.

Должны ли такие вещи, как библиотеки сокетов, которые традиционно пишутся на C, оставаться в C и храниться в отдельных исходных файлах? Это означает сохранение кода c в файлах .c и кода c ++ в файлах .cpp. При смешивании c и C ++ после разбора с g ++ будут ли какие-либо потери производительности, так как проверки безопасности типов не выполняются в C? но есть в C ++. Будет лучшим способом связать файлы исходного кода C и C ++.

Ответы [ 6 ]

7 голосов
/ 12 ноября 2008

Самая большая проблема - это вызов функции C из кода C ++ или наоборот. В этом случае вы должны убедиться, что отметили функцию как «C», используя extern "C". Вы можете сделать это в заголовочном файле напрямую, используя:

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

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

#if defined( __cplusplus )
}
#endif

Вам нужны #if s, потому что код C, который включает его, не поймет extern "C".

Если вы не хотите (или не можете) изменить заголовочный файл, вы можете сделать это в коде C ++:

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

Вы можете пометить функцию C ++ как имеющую связь с C таким же образом, а затем вызвать ее из кода C. Вы не можете сделать это для перегруженных функций или классов C ++.

Кроме этого, не должно быть проблем при смешивании C и C ++. У нас есть несколько десятилетних функций C, которые все еще используются нашим кодом C ++.

3 голосов
/ 12 ноября 2008

Как правило, следует предположить, что 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;
    }
}
3 голосов
/ 12 ноября 2008

C ++ не выполняет «типобезопасные проверки» во время выполнения, если вы не запрашиваете их (используя dynamic_cast). C ++ хорошо совместим с C, поэтому вы можете свободно вызывать библиотеки C по своему желанию и компилировать код C с помощью компилятора C ++. C ++ не подразумевает «объектно-ориентированный», и вы не должны получать никакого снижения производительности за его использование.

Если вы смешиваете код, скомпилированный с gcc и с g ++, см. Ответ Грэма.

1 голос
/ 12 ноября 2008

Здесь нет хороших жестких и быстрых правил.

Если конечный продукт всегда будет связан с main ++ C ++, то это не имеет большого значения. Как вы всегда можете создать заголовки, которые будут делать правильные вещи.

Если вы создаете библиотеку, которая должна иметь интерфейс 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 ); }
 };

Надеюсь, это поможет.

1 голос
/ 12 ноября 2008

Если у вас есть функция в C ++, которая вызывает функцию в C, которая, в свою очередь, вызывает другую функцию в C ++, и эта более поздняя функция выдает исключение, которое должно быть перехвачено первой функцией, у вас могут возникнуть проблемы, если вы не сказали C компилятор для включения генерации таблиц обработки исключений.

Для gcc это параметр -fexceptions, который включен по умолчанию для C ++, но отключен по умолчанию для C.

0 голосов
/ 12 ноября 2008

Если вы компилируете весь свой исходный код с помощью g ++, то он все скомпилируется в объектных файлах C ++ (то есть с соответствующим искажением имени и ABI C ++).

Вам нужно будет использовать трюк extern "C" только в том случае, если вы создаете библиотеки, которые должны использоваться явно приложениями C, которые должны использовать C ABI.

Если все компилируется в один исполняемый файл, тогда используйте g ++ и рассматривайте все как C ++

...