3

I believe a C++ member function declared as static has internal linkage. When I compile libbar.cpp/libbar.hpp (below) as a shared object, I find that I can call both test1 and test2 from a separate (main) program. Why is the static member function test2 available outside of its translation unit?

// bar/libbar.hpp    
struct Foo
{
  void test1();
  static void test2();
};

// bar/libbar.cpp
#include <iostream>

void Bar::test1() { std::cout << __PRETTY_FUNCTION__; }
void Bar::test2() { std::cout << __PRETTY_FUNCTION__; }

I compile the shared object with $CXX libbar.cpp -shared -fpic -o libbar.so and the main program (below) using $CXX -I bar -L bar main.cpp -Wl,-rpath,$PWD/bar -lbar. I am using GCC and Clang on Debian.

// main.cpp
#include "libbar.hpp"                                                            
                                                                                
int main(int argc, char *argv[])                                                 
{
  Bar b{};                                                                       
  b.test1();                                                                     
  b.test2();
  return 0;                                                                      
}
user2023370
  • 10,488
  • 6
  • 50
  • 83
  • 3
    See [this answer](https://stackoverflow.com/a/31305772/21285803). Basically the `static` keyword has different meanings in different contexts. At file scope and namespace scope it means internal linkage, while at class scope it means "this function does not take an object argument" – chrysante Jul 28 '23 at 09:22
  • It might be theoretically also desirable to make some non-static (as in actually object-bound) member functions static (as in file-local), but I guess C++ doesn't allow that. Weird language. – Petr Skocik Jul 28 '23 at 09:39
  • @PetrSkocik It kind of does allow it, see my answer – chrysante Jul 28 '23 at 09:42
  • 1
    @chrysante If you put the whole class in an anon namespace, won't that make each and every member function (file-local) static, though? Ideally, you'd be able to put or not put that storage class attribute on individual functions. – Petr Skocik Jul 28 '23 at 09:48
  • 2
    @PetrSkocik Yes, every member function of a class has the same linkage as the class itself. For private member functions this is indeed a shortcoming of the language, because they are always needlessly visible in the binary. – chrysante Jul 28 '23 at 09:50

1 Answers1

5

The static keyword has different meanings in different contexts.

  • At file scope and namespace scope, it means the function or variable declared as static has internal linkage.
  • At class scope it means that the function or data member is not associated with an object of that class. This implies that you can call the test2 function like this: Foo::test2().
  • At function scope it means that the variable declared static is independent of the current invokation of the function and will be initialized only once. The following function will always return the number N the N'th time it is called.
int counter() {  
    static int count = 0;
    return ++count;
}

About member functions with internal linkage:

In C++, as opposed to C, types also have linkage. Member functions of a class have the same linkage as the class itself. So to have a member function with internal linkage you have to declare the class within an anonymous namespace:

namespace {
class Foo {
    void test();
};
void Foo::test() { /* ... */ }
}

Now the class Foo has internal linkage and thus Foo::test() also has internal linkage and won't be available outside of the translation unit.

chrysante
  • 2,328
  • 4
  • 24