Я ищу несколько советов о том, что было бы подходящим интерфейсом для работы с аспектами о классах (которые имеют дело с классами), но которые не являются частью реального класса, с которым они имеют дело (мета-аспекты).Это требует некоторого объяснения ...
В моем конкретном примере мне нужно реализовать собственную систему RTTI, которая немного сложнее, чем та, которая предлагается в C ++ (я не буду вдаваться в подробности, зачем мне это нужно).Мой базовый объект - FooBase
, и каждый дочерний класс этой базы связан с FooTypeInfo
объектом.
// Given a base pointer that holds a derived type,
// I need to be able to find the actual type of the
// derived object I'm holding.
FooBase* base = new FooDerived;
// The obvious approach is to use virtual functions...
const FooTypeInfo& info = base->typeinfo();
Использование виртуальных функций для работы с типом объекта во время выполнения кажется неправильныммне.Я склонен думать о типе объекта во время выполнения как о чем-то, что выходит за рамки класса и как таковое не должно быть частью его явного интерфейса.Следующий интерфейс заставляет меня чувствовать себя намного комфортнее ...
FooBase* base = new FooDerived;
const FooTypeInfo& info = foo::typeinfo(base);
Однако, хотя интерфейс не является частью класса, реализация все равно должна будет использовать виртуальные функции, чтобы эторабота:
class FooBase
{
protected:
virtual const FooTypeInfo& typeinfo() const = 0;
friend const FooTypeInfo& ::foo::typeinfo(const FooBase*);
};
namespace foo
{
const FooTypeInfo& typeinfo(const FooBase* ptr) {
return ptr->typeinfo();
}
}
Как вы думаете, я должен использовать этот второй интерфейс (который кажется мне более подходящим) и иметь дело с немного более сложной реализацией, или я просто выберу первый интерфейс?
@ Сет Карнеги
Это сложная проблема, если вы даже не хотите, чтобы производные классы знали о том, что они являются частью RTTI ... потому чтовы действительно не можете ничего сделать в конструкторе FooBase
, который зависит от типа времени исполнения создаваемого класса (по той же причине, по которой вы не можете вызывать виртуальные методы в ctor или dtor).
FooBase
является общей основой иерархии.У меня также есть отдельный шаблон класса CppFoo<>
, который уменьшает количество шаблонов и упрощает определение типов.Есть еще один класс PythonFoo
, который работает с производными от Python объектами.
template<typename FooClass>
class CppFoo : public FooBase
{
private:
const FooTypeInfo& typeinfo() const {
return ::foo::typeinfo<FooClass>();
}
};
class SpecificFoo : public CppFoo<SpecificFoo>
{
// The class can now be implemented agnostic of the
// RTTI system that works behind the scenes.
};
Еще несколько подробностей о том, как работает система, можно найти здесь:
► https://stackoverflow.com/a/8979111/627005