Подтвердить что ты не робот

Что такое "ключевая функция" С++, как описано в золоте?

Пожалуйста, не отвечайте на вопрос "как мне решить это сообщение об ошибке?"

В сообщении об ошибке, предоставленном золотом:

/usr/bin/ld.gold: the vtable symbol may be undefined
because the class is missing its key function

Что такое key function? Я нахожу ссылку на него на странице GCC для атрибутов функций в разделе dllimport. Соответствующий текст гласит:

В целевом объекте SH Symbian атрибут dllimport также имеет другое влияние (sic) - он может вызывать информацию типа vtable и тип времени выполнения для экспортируемого класса. Это происходит, когда класс имеет конструктор dllimport или неединичную, нечистую виртуальную функцию, и для любого из этих двух условий класс также имеет встроенный конструктор или деструктор и имеет ключевую функцию, определенную в текущая единица перевода.

Из этого я убеждаюсь, что существует некоторая функция, отличная от конструкторов или деструкторов, требуемых при некоторых условиях, при использовании атрибута dllimport, в Symbian OS. Интересно, но я компилирую для Linux в Linux, а grep -r dllimport ничего не показывает. Поэтому этот параграф не применяется.

(FWIW проблема выводится (в данном случае) из деструктора undefined, но как документация, так и вывод компоновщика идут на большие усилия, чтобы отличить "ключевую функцию" от деструктора. Для других видов отсутствующих символов, компоновщик произносит имя отсутствующего символа.)

Итак, что такое key function действительно?

4b9b3361

Ответ 1

ключевая функция определяется как первая не-встроенная, виртуальная функция, объявленная в классе. Официальная gcc wiki об этом здесь.

Ответ 2

(перемещение/расширение из комментария)

Как объясняет @navylover, ключевая функция - это первая не-встроенная, виртуальная функция, определенная в классе; это важно, потому что он используется компилятором в качестве обычного маркера для определения того, в каком TU должен быть выпущен vtable (поскольку он должен испускаться только один раз) - в зависимости от того, какое TU содержит определение ключевой функции, соответствующий объектный модуль будет содержать vtable также.

Из этого следует, что если TU не определяет ключевую функцию (например, поскольку вы забыли ее определить), vtable никогда не будет излучаться, следовательно, ошибка.

золото пытается намекнуть вам в правильном направлении: если vtable отсутствует, вероятно, потому, что ключевая функция также отсутствует (опять же, потому что вы не определили или не забыли связать свой модуль), хотя он не может быть явно указан как ссылка undefined (что может привести вас к правильной дорожке), потому что в остальной части кода никто не вызывает его непосредственно 1 как в этом примере:

struct Test {
    virtual void foo();
    virtual int bar() {
        return 0;
    }
};

int main() {
    Test t;
    t.bar();
    return 0;
}

 

[[email protected] /tmp]$ g++ -fuse-ld=gold keyf.cpp 
/tmp/ccduMsT3.o:keyf.cpp:function main: error: undefined reference to 'vtable for Test'
/usr/bin/ld.gold: the vtable symbol may be undefined because the class is missing its key function

Сравните это с обычным GNU ld, который просто говорит

[[email protected] /tmp]$ g++ keyf.cpp 
/tmp/ccUr3Xyi.o: In function `main':
keyf.cpp:(.text+0x1a): undefined reference to `vtable for Test'
collect2: error: ld returned 1 exit status

Хорошо, ну и что? Это не похоже на то, что я должен явно определять vtables, поэтому это определенно не очевидно, где я должен начать искать исправление такого рода ошибок.


  • Однако такая функция может быть вызвана косвенно через указатель на базовый класс, и компоновщик по-прежнему будет показывать только ссылку undefined на vtable, а не на функцию, поскольку единственная ссылка на функцию в этом случае будет быть в vtable, который отсутствует.