Господа, тут вдарился в реверс плюсов, ну и периодически возникают всяческие вопросы. есть такой код: Код (C++): class IFace { int a, b, c; public: virtual int Test(); //IFace(); IFace() :a(0), b(0), c(0) {} }; //IFace::IFace() //:a(0), b(0), c(0) {} IFace* SetupInterface() // dummy { return nullptr; } void InstallHookStandalone() { IFace *pInterface = SetupInterface(); // external (another binary) pInterface->Test(); ... } в указанном случае линкуется нормально, но если инлайн-конструктор закомментить, а обычный(с телом вне класса) раскомментить - то тут линкер заругается на то что у IFace::Test() нету определения. происходит это, как я понимаю, потому что появился код конструктора с неявной установкой поинтера VFT, но кроме того, эту самую VFT тоже нужно загенерить и заполнить адресами. а с другой стороны, получается что при использовании инлайн конструктора код попросту некуда присобачить и он отбрасывается. поэтому и анресолведа нет. правильно понимаю?
sn0w, что тебя удивляет? У тебя у Test() и так нет определения, при этом она обьявлена как виртуальная процедура с определением по умолчанию, которое отсутствует. То что компилер в одном случае ругается, а во втором нет это вопрос открытый, по логике в обоих должен ругаться. Но видимо в твоем примере без создания инстанса объекта это прокатывает. Полностью виртуальные процедуры могут быть определены в другом бинарном модуле, поэтому вполне нормально, что определение отсутствует и компилятор это съедает, но не в твоем случае с наличием дефолтного определения.
спасибо за заметку, вот я именно и ожидал ругани от компилера, и напоминается хелп с питона - лучше явное чем неявное) и кроме того в реализации С++ от MS немало палок, например экстерналы, покрытые безымянным неймспейсом таки экспортируются из объектных модулей, в отличии от тех же жсс и сланг. на самом деле косяков дохрена, чё говорить - если студия несмотря на явно установленный ключ /DEBUG линкует бинари с ключём /DEBUG:FASTLINK от чего потом ни виндбг ни ида символы не видят ..да индусы я тут же про баг с unified initialization описывал, и этих тонкостей дохуя)
а и сланг неймспейсы некорректно генерит по мс протоколу, потому шо индусы-от-мс написали компилер так что только им одним понятно
sn0w, согласен с тобой, экстерналы в безымянном неймспейсе это плохо. Наверняка есть причина сделать именно так, вероятно был какой-то выбор наименьшего зла для разработчиков, все же MS компилирует добротный код.
С виртуальными интерфейсами в C++ дела вообще обстояли трудно до появления умных указателей, разделение проекта на разные бинарные модули создавало неопределенность при разрушении объекта в чужом бинарном модуле в виду использования какого-то чужого (не родительского) деаллокатора памяти. Низкоуровневое наследие требует жертв ))
sn0w, здесь, похоже, следующая логика. Так как конструктор короткий и его определение присутствует в теле класса, то компилер генерит тело в lazy-режиме: если конструктор где-то используется, то генерит код. Если не используется - то не генерит. У вас в коде нигде конструктор не вызывается, а потому генерить его нет смысла. А если нигде не создаётся инстанс объекта - то и таблица виртуальных функий нигде не используется. Во втором случае вы явно уже говорите компилятору, что надо генерить код, объявляя реализацию конструктора вне класса. Поэтому генерируется код конструктора, после чего мы и натыкаемся на проблему, что таблица виртуальных функций-то неполная, оказывается.
господа, спасибо за ответы, в целом несколько разобрался. но, вообщем теже designated initializers вернут вроде как в цпп 20, странно что они их не заметили в 11, вообщем всем бобра)
да это в курсе, как и про неявные конструкторы, которые инициализируют помимо vft нестатические мемберы с in-class definition, неявно добавляя конструктор. а вот в таких местах я бы таки добавил хотябы варнинг
на сей раз прочитал вдумчиво. да и поэксперементировал с = delete; в целом в вопросе разобрался, спасибо за помощь.
ну прикол в том что понятно что безымянные имена генерятся вроде как от имени, пути/ имени файла, по крайней мере это чтото статическое, не проверял. например манглинг неймспейса анонимного в анонимном попросту конкатит цифру вложенности(MSC), но, на выходе в объектных модулях эти имена PUBLIC, то есть видимы с других модулей. хотя в том же g++ нифига, static.