You probably noticed that String
doesn't define a constructor, a destructor or an assignment operator. This wasn't an oversight. In spite of its C++ interface, String
still remains a POD type
, which means that its binary layout is identical in C and C++. Indeed, you're limited with respect to the C++ features that you may add to String
but you still have enough leeway to make C++ users content. To summarize, adding any of the following features to String
will make it a non-POD type:
- virtual functions
- user-defined destructor
- user-defined assignment operator
- user-defined copy constructor
- user-defined constructor
- reference members
- data members that are pointers to members
- base class(es)
- non-POD member objects
Using C++ Functionality in C
Thus far, this article has focused on the source code level of sharing declarations between the two languages. You can also utilize compiled C++ functionality in C by wrapping C++ code in an intermediary layer. Here's an example.
Suppose you're maintaining a C application that reads char* strings and stores them as char**. Your task is to sort these strings alphabetically and print them onscreen. Instead of wading through strcmp(), qsort() and pointer mayhem, you want an elegant, STL-based solution. It's doable.
First, declare an intermediary function as extern "C". This function will be compiled as a C++ function but it's callable from C, too. C doesn't recognize the extern "C" linkage specification. Therefore, use #ifdef-#endif to hide this part from the C compiler:
void func (char **s, int n);
// end of func.h
is implemented in a .cpp
source file that's compiled separately. Here's a typical implementation that uses all sorts of STL conveniences:
extern "C" void func (char **s, int n)
for (int i=0; i<n; i++)
//print the contents of vs using a stream iterator
as usual. Next, add its declaration to your C application:
A C compiler doesn't care how func()
is implemented; it only inserts a call to a function with this name into main.obj
. It's the linker's job to resolve the call to the same function defined in func.obj
. Since the linker sees only the .obj
files, the extern "C"
linkage specification is mandatory. It guarantees that both C and C++ generate the same symbol for func()
. Without extern "C"
, you'll get a linkage error.
Can func() use any C++ feature? Yes, almost. Virtually all implementations nowadays use a single runtime library for C and C++ so yanking compiled C++ code into C should "just work". There's one caveat, though: C functions do not propagate C++ exceptions. If func() throws an exception, your application will behave unpredictably. To avoid this, func() must handle all exceptions, if any, locally.