C++ primer 5th ed. external linkage and function overloading

94 views Asked by At

I have this from C++ primer 5th edition: External Linkage:

If one function among a set of overloaded functions is a C function, the other functions must all be C++ functions:

class SmallInt { /* . . .   */ };
class BigNum { /* . . .   */ };
// the C function can be called from C and C++ programs
// the C++ functions overload that function and are callable from C++

extern "C" double calc(double);
extern SmallInt calc(const SmallInt&);
extern BigNum calc(const BigNum&);

The C version of calc can be called from C programs and from C++ programs. The additional functions are C++ functions with class parameters that can be called only from C++ programs. The order of the declarations is not significant.

  • So what I understood from these declarations is that I can put them in a header. e.g:

    // calc.h
    #ifdef __cplusplus
    
    class SmallInt { /* . . .   */ };
    class BigNum { /* . . .   */ };      
    
    // C++ functions can be overloaded
    extern SmallInt calc(const SmallInt&);
    extern BigNum calc(const BigNum&);
    extern "C" 
    
    #endif
    
    double calc(double); // C function
    
  • So do I need to define C version in a C source file and C++ version in a C++ source file?

    // calc.c
    #include "calc.h"
    
    double calc(double){} // do_something
    
    // calc.cxx
    #include "calc.h"
    
    SmallInt calc(const SmallInt&){} // do_something
    BigNum calc(const BigNum&){} // do_something
    
  • Now I need to compile this way:

     gcc print.c -c && g++ main.cxx print.cxx print.o -o prog
    
  • It works just fine but am I correct about my guesses and implementing this code?

  • What is the point in extern in the C++ versions (calc(const SmallInt&) and calc(const BigNum&)) as long as they cannot be compiled with a C compiler? Thank you so much!

2

There are 2 answers

7
JDługosz On

No, you can define all the functions in CPP source files, and call them from C (easily, if they are declared as having C linkage).

One source file, print.cxx, can have the implementation (function bodies) for all three functions. It is compiled as C++, and the implementation of double calc(double) can certainly use C++ to do its work.

A C program can be linked with that .o file, and call calc(double).

It can be useful to make C-callable API for a C++ library, and you can see that that must be part of the C++ source in order to work.

When you write extern "C", you are saying you will support calling that function from a C source file. It does not mean that the function is itself written in C.

0
Mike Dog On

When we talking about "C linkage", in fact we just care about header files. Making the function signature "extern C" in the header files is enough for foreign language (like rust/go) to call it.

And the so-called "C linkage" has a counterpart called "C++ linkage". The later has parameter types in the signature, but the former is just plain simple function name.

For example: compile this file:

// example.cpp
#include <array>
using namespace std;
extern "C"
double funcAlpha(double, int){
    return 0;
}

double funcBeta(double, int){
    return 0;
}

int main(){
}

run gcc example.cpp -o a.out && objdump -t a.out | grep func, you will get

000000000040046e g     F .text  000000000000001c              _Z8funcBetadi
0000000000400452 g     F .text  000000000000001c              funcAlpha

where d = double, i = int