English version: https://telegra.ph/Virtual-Method-Anchor-08-28
В стандартах кодирования LLVM есть пункт Provide a Virtual Method Anchor for Classes in Headers: https://llvm.org/docs/CodingStandards.html#provide-a-virtual-method-anchor-for-classes-in-headers
Там говорится, что если класс объявлен в заголовочном файле и имеет таблицу виртуальных функций, то разработчик должен предоставить хотя бы один out-of-line метод в соответствующем .cpp файле. Иначе компилятор будет копировать таблицу виртуальных функций и RTTI информацию в каждый объектный файл.
Например, такой код будет выдавать предупреждение с использованием флага -Wweak-vtables:
// A.hи даже такой:
class A {
public:
virtual ~A() {}
};
warning: A has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit
// A.hЧтобы избежать этого предупреждения, нужно перенести деструктор в .cpp файл:
class A {
public:
virtual ~A() = default;
};
// A.h"Да кому это нужно", — скажете вы? "Ведь все равно линкер объединит все таблицы виртуальных функций в одну".
class A {
public:
virtual ~A();
};
// A.cpp
A::~A() = default;
Да, это правда, и линкер на самом деле на это способен. Но не забывайте, что это увеличивает время линковки. Например, в таком проекте как Chromium, где десятки тысяч классов, данная оптимизация может сэкономить несколько минут (!) линковки и она обязательна.
Кстати, можно просто в каждом подобном классе делать специальный anchor-метод, как в LLVM, но так придется больше писать:
https://github.com/llvm-mirror/llvm/blob/f17bde5ddcb1947199f44b44af6107f9209dbdd4/include/llvm/ExecutionEngine/ObjectCache.h#L24
https://github.com/llvm-mirror/llvm/blob/f17bde5ddcb1947199f44b44af6107f9209dbdd4/lib/ExecutionEngine/ExecutionEngine.cpp#L65