Эта часть вопроса содержит справочную информацию и может быть проигнорирована
Я работаю над библиотекой шаблонов, которая в значительной степени зависит от использования любопытно повторяющегося шаблона шаблона. Идея структуры класса заключается в том, что пользователь может либо
1). Используйте предопределенные классы со стандартными методами. Эти классы являются очень простыми листьями базового класса, которые предоставляют только конструкторы/деструкторы, объявляют переменные-члены и объявляют базовый класс(ы) как друг(и). Все методы, которые работают с переменными-членами производных классов, определены в базовом(их) классе(ах).
2). Используйте базовые классы для создания собственных расширений. Этот метод также позволяет пользователям вводить свои собственные методы, которые работают с теми же переменными-членами.
Только одноуровневое наследование обеспечивается проектом.
Мой вопрос, в первую очередь, касается пункта 2. В текущей реализации пользователь должен неявно определять все конструкторы (т.е. описывать полный процесс выделения памяти для динамических переменных членов класса и т. д.).
Вопрос
Пример ниже демонстрирует исследование возможности использования CRTP для предоставления определения выделения памяти переменных кучи производных классов в конструкторах базового класса.
Часть базового класса
template<class TLeafType, class MyClass> class sysBaseDiscreteTrajectoryPoint {
...
//one of the base constructors
sysBaseDiscreteTrajectoryPoint(const MyClass& MyClassInstance) {
std::cout << "Base additional constructor called" << std::endl;
std::cout << asLeaf().Point << std::endl;
asLeaf().Point=new MyClass(MyClassInstance);
std::cout << asLeaf().Point << std::endl;
}
TLeafType& asLeaf(void) {
return static_cast<TLeafType&>(*this);
}
...
};
Производный класс:
template<class MyClass>
class sysDiscreteTrajectoryPoint: public sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass> {
...
friend class sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass>;
private:
MyClass* Point;
public:
sysDiscreteTrajectoryPoint(const MyClass& MyClassInstance): sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass>(MyClassInstance){
std::cout << "Derived additional constructor called " << std::endl;
std::cout << Point << std::endl;
std::cout << *Point << std::endl;
}
...
}
главный:
int a(5);
sysDiscreteTrajectoryPoint<int> A(a);
Код производит следующий вывод:
Base additional constructor called
0x847ff4
0x8737008
Derived additional constructor called
0x8737008
5
Derived destructor called
Base destructor called
Результат предполагает, что концепция может быть осуществимой. Однако у меня есть два вопроса.
1). Я хотел бы убедиться, что я понимаю все процессы, происходящие во время выполнения кода. В частности, меня интересует эффективность процесса, так как мне может понадобиться инстанцировать значительное количество объектов из классов, представленных выше, и я хотел бы понять, что происходит с Point
(есть ли скрытые переопределения?)
2). Вопрос связан с использованием библиотеки boost
для определения умных указателей для членов производного класса. Когда я попытался заменить необработанный указатель на boost::shared_ptr
, я получил ошибку ошибки сегментации при попытке выделить память для члена производного класса через базовый класс. Важные разделы кода показаны ниже.
Часть базового класса:
template<class TLeafType, class MyClass> class sysBaseDiscreteTrajectoryPoint {
...
//one of the base constructors
sysBaseDiscreteTrajectoryPoint(const MyClass& MyClassInstance) {
std::cout << "Base additional constructor called" << std::endl;
std::cout << asLeaf().Point << std::endl;
asLeaf().Point.reset(new MyClass(MyClassInstance));
std::cout << asLeaf().Point << std::endl;
}
TLeafType& asLeaf(void) {
return static_cast<TLeafType&>(*this);
}
...
};
Часть производного класса:
template<class MyClass>
class sysDiscreteTrajectoryPoint: public sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass> {
...
friend class sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass>;
private:
boost::shared_ptr<MyClass> Point;
public:
sysDiscreteTrajectoryPoint(const MyClass& MyClassInstance): sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass>(MyClassInstance){
std::cout << "Derived additional constructor called " << std::endl;
std::cout << Point << std::endl;
std::cout << *Point << std::endl;
}
...
}
главный:
int a(5);
sysDiscreteTrajectoryPoint<int> A(a);
Код производит следующий вывод:
Base additional constructor called
0x28d324
Segmentation fault
Я также пробовал scoped_ptr
. Однако во время выполнения это не удалось, но с другой ошибкой:
Base additional constructor called
*** glibc detected *** ./TestSystem: free(): invalid pointer: 0x00d3fff4 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6b961)[0xc4e961]
...
Предполагаю, что это связано со спецификой работы boost smart pointers. Кто-нибудь знает, как решить эту проблему?