Do classes have external linkage?

Viewed 6201

I have 2 files A.cpp and B.cpp which look something like

A.cpp
----------
class w
{
public:
    w();
};


B.cpp
-----------
class w
{
public:
    w();
};

Now I read somewhere (https://en.cppreference.com/w/cpp/language/static) that classes have external linkage. So while building I was expecting a multiple definition error but on the contrary it worked like charm. However when I defined class w in A.cpp, I got the redefinition error which makes me believe that classes have internal linkage.

Am I missing something here?

6 Answers

Seeing as you can't use static on a class, the only way to give a 'class' static linkage is to define the type in an anonymous namespace. Otherwise, it will have extern linkage. I put class in quotation marks because a class, which is a type, does not have a linkage, instead it is referring to the linkage of the symbols defined in the class scope (but not the linkage of an object made using the class). This includes static members and methods and non-static methods, but not non-static members as they are only part of the class type definition and do not additionally declare / define actual symbols.

The 'class' having static linkage means that the members and methods that would have had external linkage or external comdat linkage now both have static linkage only -- they are now local symbols, although the effect of inline at the compiler level still applies (i.e. it does not emit a symbol if it is not referenced in the translation unit) -- it's just no longer an external comdat symbol at assembler level, it's a local symbol. This is the case even if the member or method of the class is defined out-of-line and out of an anonymous namespace, it will still have static linkage.

If you declare the class type in an anonymous namespace, you will not be able to define the type outside of an anonymous namespace and it will not compile. You need to define it in the same anonymous namespace or a different anonymous namespace in the translation unit (different anonymous namespace doesn't matter because they're all combined into the same anonymous anonymous namespace name _GLOBAL__N_1).

This is the only way to change the linkage of members or methods of a class / struct because static will make it a static member and does not change the linkage, static will be ignored on out of line definitions, and extern is not allowed on class members / functions.

Related