Search code examples
c++private

Internal linkage for C++ private functions?


When I write object-oriented code in C, I normally put the struct definition together with the public functions in a header file, and implement the public functions in a separate .c file. I give the static keyword to all functions that are "private" for this class, and implement them in the .c file as well. The public functions can then call the private functions belonging to the same class. The private functions cannot be called from outside, thanks to the static keyword, so GCC can optimize many of these functions. They are often inlined and the original function is entirely deleted from the output object file.

Now to my question: how can I do the same with C++ classes?

Let's say I have a header file:

class A {
    int private_field;
    int private_function();
public:
    int public_function();
};

And my .cpp file:

#include <iostream>
#include "A.h"

int A::private_function() {
    std::cin >> private_field;
    return private_field;
}

int A::public_function() {
    return private_function() + 4;
}

In the resulting object file, private_function is left as a separate symbol, and public_function calls private_function (not inlined). I would like to give private_function internal linkage, so the compiler can do the same optimizations as when I use C. I have tried with anonymous namespaces and static, but I can't get it to work as I would like to. How to do it correctly, is it even possible? I use GCC.


Solution

  • Class members never have internal linkage. The Standard says (section 9.3):

    Member functions of a class in namespace scope have external linkage. Member functions of a local class have no linkage.

    So if you want to create helper functions with internal linkage, you have to use a non-member.

    static int private_function(A* pThis);
    
    class A
    {
        int private_field;
        friend int private_function(A* pThis);
    public:
        int public_function();
    };
    

    and then

    #include <iostream>
    #include "A.h"
    
    static int private_function(A* pThis)
    {
        std::cin >> pThis->private_field;
        return private_field;
    }
    
    int A::public_function() {
        return private_function(this) + 4;
    }
    

    Please note this rule from the Standard (section 11.3):

    A function first declared in a friend declaration has external linkage. Otherwise, the function retains its previous linkage.