What are best practices with regards to C and C++ coding standards? Should developers be allowed to willy-nilly mix them together. Are there any complications when linking
There are no good hard and fast rules here.
If the end product will always be linked with a C++ main() then it does not really matter. As you can always create headers that will do the correct thing.
If you are creating a library that needs to have a C and C++ interface but you can't assume the C++ linker then you will need to make sure you separated the C API from the C++ cleanly. At this point it is usually cleaner to do all the work in C and use C++ classes to proxy to the C.
For example:
/* 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 ); }
};
I hope this helps.
One should generally assume that c++ can throw exceptions, hence the c wrapper functions in your block, ought to catch them, and morph them into nice error codes that the c caller can digest.
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;
}
}
If you have a function in C++ which calls a function in C which in turn calls another function in C++, and this later function throws an exception which should be caught by the first function, you can have problems unless you told the C compiler to enable generation of the exception handling tables.
For gcc, this is the -fexceptions parameter, which is enabled by default for C++ but disabled by default for C.
If you compile all your source with g++ then it is all compiled in C++ object files (i.e. with the appropriate name mangling and the C++ ABI).
You will only need to use the extern "C" trick if you are building libraries that need to be used by explicitly C applications that need to use the C ABI.
If everything is being compiled into a single executable then use g++ and treat everything as C++
C++ doesn't do 'typesafe checks' at run time unless you ask for them (by using dynamic_cast
). C++ is highly compatible with C, so you may freely call C libraries as you wish and compile C code with a C++ compiler. C++ does not imply 'object-oriented', and you should get no performance penalty from using it.
If you mix code compiled with gcc and with g++, see Graeme's answer.
The biggest issue is calling a C function from C++ code or vice versa. In that case, you want to make sure you mark the function as having "C" linkage using extern "C"
. You can do this in the header file directly using:
#if defined( __cplusplus )
extern "C" {
#endif
extern int myfunc( const char *param, int another_one );
#if defined( __cplusplus )
}
#endif
You need the #if
s because C code that includes it won't understand extern "C"
.
If you don't want to (or can't) change the header file, you can do it in the C++ code:
extern "C" {
#include "myfuncheader.h"
}
You can mark a C++ function as having C linkage the same way, and then you can call it from C code. You can't do this for overloaded functions or C++ classes.
Other than that, there should be no problem mixing C and C++. We have a number of decades-old C functions that are still being used by our C++ code.