виртуальные методы и конструкторы?

У меня есть курица<-> проблема с яйцом.
Я хочу создать интерфейс для контейнерных классов, чтобы я мог форсировать реализацию определенных attr-аксессоров и других методов, и в то же время я хочу иметь возможность вызывать эти методы из конструкторов контейнеров.
Но, как мы знаем, вызов виртуального метода из Constructor будет вызывать методы базового класса из-за последовательности, в которой вызываются конструкторы в иерархии.
Итак, проблема в том, что мне нужны виртуальные методы для принудительной реализации, но это то, что я не могу вызвать в конструкторе.
РЕДАКТИРОВАТЬ: Я хочу, чтобы когда я должен был реализовать класс контейнера (C1, C2 …), был вынужден реализовать определенные методы И во-вторых, я хочу иметь возможность использовать эти методы в конструкторах контейнера. Проще говоря, я хочу реализовать требование ИНТЕРФЕЙСА, объявление-только-mixin. Спасибо
Как вы решаете эту проблему?
Ниже приведен пример кода.

#include <iostream>
using namespace std;

class Base {
public:
virtual void myvirt() { cout << "Base::virt()" << endl; };
};

class C1 : public Base {
public:
C1() {cout << "C1()" << endl; C1::myvirt(); };
C1(int i) { cout << "C1(int)" << endl; }
void myvirt() { cout << "C1::virt" << endl;}
};class C2 : public Base {
public:
C2() {cout << "C2()" << endl; C2::myvirt();};
C2(int i) { cout << "C2(int)" << endl; }
void myvirt() { cout << "C2::virt" << endl;}
};

template<class C = C1>
class Sc: public C {
public:
Sc() : C() { cout << "Sc()" << endl; };
Sc(int n): C(n)  { cout << "Sc(int)" << endl; };

};int main() {
Sc<C2>  $sx(12);
return 0;
}

Так же, как я спрашиваю, есть ли способ принудительной реализации в классах-потомках конкретных Constructors ().
Что-то вроде «виртуальных конструкторов».

1

Решение

Просто сделайте конструктор тривиальным, а затем, после того как конструктор вернется, вызовите какую-то функцию инициализации, чтобы завершить конструирование объекта. Вы также можете использовать клон идиома, в зависимости от того, как вы хотите решить, какой тип объекта построить.

Вы также можете иметь класс-оболочку, конструктор которого сначала создает внутренний класс, а затем вызывает его виртуальную функцию инициализации.

Обновление: вы можете обернуть как это:

 Class Wrapper : public Inner
{
public:
Wrapper(...) : Inner(...)
{
init();
}
virtual ~Wrapper();
}

Теперь вы можете просто сделать

 Wrapper foo(whatever);

И вы можете использовать foo так же, как Inner,

5

Другие решения

Вы не должны вызывать виртуальные функции во время строительства или разрушения в первую очередь. Это просто не очень хорошая практика.

Выдержка из пункта 9 Effective C ++, 3-е издание:

Есть веская причина для такого, казалось бы, нелогичного поведения. Поскольку конструкторы базового класса выполняются до конструкторов производного класса, члены данных производного класса не были инициализированы при запуске конструкторов базового класса. Если виртуальные функции, вызываемые во время создания базового класса, переходят к производным классам, функции производного класса почти наверняка будут ссылаться на локальные члены данных, но эти члены данных еще не были бы инициализированы. Это был бы безостановочный билет на неопределенное поведение и сеансы отладки поздно ночью. Обращение к частям объекта, которые еще не были инициализированы, по своей природе опасно, поэтому C ++ не дает вам возможности сделать это.

http://www.artima.com/cppsource/nevercall.html

3

По вопросам рекламы [email protected]