From Large-Scale C++ Software Design (Lakos), page 652:
The question is, "In which unique translation unit will the compiler deposit the virtual table definition(s) for a given class?". The trick employed by CFRONT (and many other C++ implementations) is to place the external virtual tables in the translation unit that defines the lexically first non-inline function that appears in the class (if one exists).
Is this still the case with the most used compilers (GCC and Visual C++)? Or was it ever?
GCC happens to document that it behaves as described in the question (http://gcc.gnu.org/onlinedocs/gcc/Vague-Linkage.html):
VTables
C++ virtual functions are implemented in most compilers using a lookup table, known as a vtable. The vtable contains pointers to the virtual functions provided by a class, and each object of the class contains a pointer to its vtable (or vtables, in some multiple-inheritance situations). If the class declares any non-inline, non-pure virtual functions, the first one is chosen as the “key method” for the class, and the vtable is only emitted in the translation unit where the key method is defined.
Note: If the chosen key method is later defined as inline, the vtable will still be emitted in every translation unit which defines it. Make sure that any inline virtuals are declared inline in the class body, even if they are not defined there.
However, even in situations where there might be several vtables across several object files (as can happen if the 'key method' turns out to be inline), the compiler arranges for the duplicates to be ignored if possible, but the duplicates may end up using space in the final binary if the target doesn't support COMDAT:
When used with GNU ld version 2.8 or later on an ELF system such as GNU/Linux or Solaris 2, or on Microsoft Windows, duplicate copies of these constructs will be discarded at link time. This is known as COMDAT support.
On targets that don't support COMDAT, but do support weak symbols, GCC will use them. This way one copy will override all the others, but the unused copies will still take up space in the executable.
For targets which do not support either COMDAT or weak symbols, most entities with vague linkage will be emitted as local symbols to avoid duplicate definition errors from the linker. This will not happen for local statics in inlines, however, as having multiple copies will almost certainly break things.
FWIW, GCC seems to use a symbol that starts with __ZTV
for the vtable.
As far as MSVC is concerned, some empirical testing with VC++10 (I don't think MS documents the behavior) shows that it seems that VC doesn't attempt to limit the vtable to a single object file. Since Microsoft knows that it can rely on the linker supporting COMDAT sections and since constructors are the only functions that use a vtable directly (all other vtable uses are indirect through the object pointer, I believe), it looks like VC just places a copy of the vtable in any object file where a constructor is instantiated. For classes that use the compiler generated ctor, that would be anywhere an object of that type is constructed.