|
решить такую проблему.
Проект на С++. Над проектом работают несколько человек. Будем считать, что их работа независимая. В проекте, как и положено, есть системный интегратор, который делает инициализации всех нужных классов, передавая туда, вЕдомые только ему одному параметры.
У меня есть некий класс А, который среди прочего включает в себя указатель на абстрактный класс В, ИНТЕРФЕЙС КОТОРОГО Я ПРОПИСАЛ. Далее я описал и реализовал все методы класса А. В конструкторе класса А я должен создать одну (а в общем случае несколько) экземпляров класса, унаследованного от класса B. За реализацию класса В ответственность несет другой человек. Как он назовет этот класс, я не знаю, и знать не хочу. Более того, может, ему взгрустнется описать еще десять разных классов-потомков класса В с разной начинкой. А системный интегратор уже сам будет решать, какой из этих классов будет реально использоваться. Системный интегратор решает, какой из потомков класса В будет использоваться (а может, он это не решает на уровне компиляции, а инициализирует класс динамически, в run-time). И задача системного интегратора - вызвать конструктор моего класса А, в качестве параметра которого он должен будет передать ссылку на тот класс В, который реально будет использоваться в системе и с которым Я УЖЕ БУДУ РАБОТАТЬ.
Ни системный интегратор, ни тот человек, кто будет реализовывать классы-потомки класса В не знают и не должны знать, что будет делаться внутри моего класса А. Все, что им нужно сделать системному интегратору, когда он будет инициализировать систему, и в том числе мой класс А - это подставить в конструктор моего класса А ссылку на тот класс В, который реально и будет мной эксплуатироваться (который я если захочу - создам, и создам столько экземпляров, сколько мне нужно, а захочу - вообще не буду создавать; естественно, что и удаление созданных экземпляров классов, которые я создам, также будет на моей совести). В моем желании нет ничего особенного. Ведь я же прописал интерфейс класса В, значит я знаю, как распоряжаться с потомками этого класса. По-крайней мере создать, удалить объект и вызвать те его методы, которые описаны как виртуальные в классе В, я могу.
Вот тут-то и возникает проблемка. Во-первых, в идеале класс В должен иметь виртуальный конструктор. Понимаю, что в С++ в отличие от Дельфи такого не бывает. Кроме того, нет возможности передать ссылку на класс, которая в Дельфи также имеется.
Ладно. Попробуем это обойти. В конструктор класса А в качестве переметров будем передавать указатель на таблицу виртуальных методов (VMT) класса-потомка В (ясно, что VMT уникальна для каждого класса). А также необходимо будет передать размер класса В, с которым я должен буду работать. Имея эти два параметра, я смогу создать класс при помощи malloc, прописав затем в свежесозданном экземпляре указатель на VMТ, который мне был передан в качестве первого параметра, и вызвав после этого виртуальную функцию (назовем ее Init), которая инициализирует этот класс (эта функция Init будет играть своеобразную роль виртуального конструктора). По-хорошему, для класса В можно и оператор New переопределить, который все это дело оформит в одном флаконе. Вроде бы все клеится. Остается одна загвоздка - каким образом системный интегратор сможет получить указатель на VMT класса, который он знает заранее, но не создавая экземпляра этого класса (ведь создавать экземпляры буду уже я в конструкторе класса А)? Проблема моя в том, что вроде как получается, что до создания объекта адреса VMT всех классов держатся компилером в секрете. Может, кто знает, как раскрыть этот секрет?
П.С. Я даже решил для себя проблему, как получить указатели на все существуюие VMT вообще. Но проблема в том, что я не буду знать, какая VMT за каким классом закреплена.