Я думаю, вы были правы в том, что изначально я не поняла ваш вопрос.
Я думаю, что вы пытаетесь втиснуть квадратную форму в круглое отверстие ... оно не совсем подходит для C ++.
Вы можете принудить, чтобы ваш контейнер содержал указатели на объекты данного базового макета, а затем разрешить фактическое указание объектов произвольной композиции оттуда, предполагая, что вы, как программист, только фактически размещаете объекты, которые на самом деле имеют идентичные макеты памяти (данные-члены - для класса нет такого понятия, как макет-функция-член, если у него нет виртуальных объектов, которых вы хотите избежать).
std::vector< boost::shared_ptr<IShape> > shapes;
ПРИМЕЧАНИЕ: при абсолютном МИНИМАЛЕ у вас все еще должен быть виртуальный деструктор, определенный в IShape, иначе удаление объекта будет с треском провалено
И у вас могут быть классы, которые все получают указатель на общее ядро реализации, так что все композиции можно инициализировать с помощью элемента, который они совместно используют (или это можно сделать статически в виде шаблона с помощью указателя - общих данных).
Но дело в том, что, если я пытаюсь создать пример, я теряю равновесие в секунду, когда пытаюсь рассмотреть: какие данные используются всеми формами? Я полагаю, у вас может быть вектор точек, который может быть таким же большим или маленьким, как требуется для любой фигуры. Но даже в этом случае Draw () является по-настоящему полиморфным, это не реализация, которая может совместно использоваться несколькими типами - она должна быть настроена для различных классификаций фигур. то есть круг и многоугольник не могут совместно использовать один и тот же Draw (). А без vtable (или какой-либо другой конструкции указателя динамической функции) вы не можете отличить функцию, вызываемую от какой-либо общей реализации или клиента.
Ваш первый набор кода полон запутанных конструкций. Может быть, вы можете добавить новый, упрощенный пример, который PURELY показывает - более реалистично - что вы пытаетесь сделать (и игнорируете тот факт, что в C ++ нет нужной вам механики - просто продемонстрируйте, как должна выглядеть ваша механика) ).
По-моему, я просто не получаю практического применения, если только вы не пытаетесь сделать что-то вроде следующего:
Возьмите класс COM, который наследуется от двух других интерфейсов COM:
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser
{
...
};
А теперь у меня есть шаблон наследования алмазов: IShellBrowser в конечном итоге наследует IUnknown, как и ICommDlgBrowser. Но кажется невероятно глупым писать свою собственную реализацию IUnknown: AddRef и IUnknown :: Release, которая является очень стандартной реализацией, потому что нет способа заставить компилятор позволить другому унаследованному классу предоставлять недостающие виртуальные функции для IShellBrowser и / или ICommDlgBrowser.
То есть мне приходится:
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser
{
public:
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++m_refcount; }
virtual ULONG STDMETHODCALLTYPE Release(void) { return --m_refcount; }
...
}
потому что я не знаю, как "наследовать" или "вставлять" эти реализации функций в MyShellBrowserDialog из любого другого места , которое фактически заполняет необходимую виртуальную функцию-член для IShellBrowser или ICommDlgBrowser.
Я могу, если реализации были более сложными, вручную связать виртуальную таблицу с унаследованным разработчиком, если я захочу:
class IUnknownMixin
{
ULONG m_refcount;
protected:
IUnknonwMixin() : m_refcount(0) {}
ULONG AddRef(void) { return ++m_refcount; } // NOTE: not virutal
ULONG Release(void) { return --m_refcount; } // NOTE: not virutal
};
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser, private IUnknownMixin
{
public:
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return IUnknownMixin::AddRef(); }
virtual ULONG STDMETHODCALLTYPE Release(void) { return IUnknownMixin::Release(); }
...
}
И если бы мне нужен был встроенный модуль, чтобы фактически ссылаться на самый производный класс для взаимодействия с ним, я мог бы добавить параметр шаблона в IUnknownMixin, чтобы дать ему доступ к себе.
Но какие общие элементы мог бы иметь или выиграть мой класс от того, что IUnknownMixin не мог сам предоставить?
Какие общие элементы мог бы иметь любой составной класс, к которому различные миксины хотели бы иметь доступ, который они должны были извлечь из себя? Просто пусть mixins принимает параметр типа и получает к нему доступ. Если его данные экземпляра наиболее производные, то у вас есть что-то вроде:
template <class T>
class IUnknownMixin
{
T & const m_outter;
protected:
IUnknonwMixin(T & outter) : m_outter(outter) {}
// note: T must have a member m_refcount
ULONG AddRef(void) { return ++m_outter.m_refcount; } // NOTE: not virtual
ULONG Release(void) { return --m_outter.m_refcount; } // NOTE: not virtual
};
В конечном итоге ваш вопрос по-прежнему несколько смущает меня. Возможно, вы могли бы создать этот пример, который демонстрирует ваш предпочтительный естественный синтаксис, который что-то четко выполняет, поскольку я просто не вижу этого в вашем первоначальном посте, и я не могу вычеркнуть его из игры с этими идеями. 1042 *