Что означает clang's-Wweak-vtables?
Я в принципе не понимаю из Clang -Wweak-vtables
. Вот что я наблюдал до сих пор:
случае один: (триггеры предупреждение)
class A {
public:
virtual ~A(){}
};
class B : public A {
public:
virtual ~B(){}
};
int main(){}
случае два: (не вызывает предупреждение)
class A {
public:
virtual ~A(){}
};
int main(){}
три кнопки: (не вызывает предупреждение)
class A {
public:
virtual ~A();
};
A::~A(){}
class B : public A {
public:
virtual ~B(){}
};
int main(){}
случае четыре: (триггеры предупреждение)
class A {
public:
virtual ~A(){}
virtual void fun(){}
};
class B : public A {
public:
virtual ~B(){}
};
int main(){}
случае пять: (не вызывает внимание)
class A {
public:
virtual ~A(){}
virtual void fun();
};
class B : public A {
public:
virtual ~B(){}
};
int main(){}
случае шесть: (не вызывает предупреждение)
class A {
public:
virtual ~A(){}
virtual void fun(){}
};
class B : public A {};
int main(){}
Дело номер семь: (не вызывает предупреждение)
class A {
public:
virtual ~A(){}
virtual void fun(){}
};
class B : public A {
public:
virtual void fun(){}
};
int main(){}
точное предупреждение
warning: 'A' has no out-of-line virtual method definitions; its vtable
will be emitted in every translation unit [-Wweak-vtables]
таким образом, по-видимому, если я не объявляю не встроенную виртуальную функцию в классе, это вызывает некоторые вид проблемы тогда и только тогда, когда я получаю от него и производный класс имеет виртуальный деструктор.
вопросы:
- почему это проблема?
- почему это исправляется путем объявления виртуальной функции? (Предупреждение говорит о определения)
- почему предупреждение не возникает, когда я не производный от класса?
- почему предупреждение не появляется, когда производный класс не имеет виртуального деструктора?
1 ответ:
если все класса
virtual
методы встроены, компилятор не может выбрать единицу перевода, в которой можно разместить одну общую копию vtable - вместо этого копия vtable должна быть помещена в каждый объектный файл, который в ней нуждается. На многих платформах компоновщик может унифицировать эти несколько копий, либо отбрасывая повторяющиеся определения, либо сопоставляя все ссылки на одну копию, поэтому это только предупреждение.осуществляет из-за линии позволяет компилятору выбрать модуль преобразования, реализующий этот метод out-of-line в качестве "дома" для сведений о реализации класса, и помещает одну общую копию таблицы vtable в ту же единицу преобразования. Если несколько методов находятся вне строки, компилятор может сделать произвольный выбор метода, если этот выбор определяется только объявлением класса; например, GCC выбирает первый нестрочный метод в порядке объявления.
если вы не переопределить любой метод класса,
virtual
ключевое слово не имеет заметного эффекта, поэтому компилятор не должен выдавать vtable для класса. Если вы не производны отA
, или если вы не можете объявить деструктор производного классаvirtual
, В и такA
таблица vtable опущена. Если объявить дополнительные строкиvirtual
метод для подавления предупреждения, а также сделать что-то, что переопределяет метод вA
реализация невстроенныеvirtual
(и его сопроводительная копия таблицы vtable) должна быть предоставлена в связанной единице перевода, иначе связывание не удастся, потому что отсутствует таблица vtable.