Что я хотел бы знать, это:
struct GenericBase{
};
struct MyObject : public GenericBase{
virtual void method() = 0;
};
struct MyAlias : public MyObject{
//supposed to have exactly the same layout as MyObject (?)
};
struct MyImpl : public MyObject{
virtual void method() { cout << "method implementation \n"; }
//note that MyImpl inherit MyObject, but we cast it to MyAlias
};
void test_alias(){
MyImpl m;
GenericBase* ptr = &m;
MyAlias* new_ptr = static_cast<MyAlias*>(ptr); //here is the cast
new_ptr->method();
}
РЕДАКТИРОВАТЬ:
Я не могу использовать RTTI, ни шаблоны
Ответ: Это не портативный.
struct MyAlias : public MyObject{
//supposed to have exactly the same layout as MyObject (?)
};
Этот комментарий неверен: размер MyAlias зависит от реализации и не определяется стандартом (это зависит, например, от требований выравнивания целевой архитектуры: компилятор может добавить биты заполнения в производный объект или от того, как метод диспетчеризация осуществляется и т.д ..)
Этот фрагмент переносной?
Нет, это не портативно. Рассуждать как сказано в @quantdev«s ответ.
Что бы я сделал, это опустить GenericBase
и использование полиморфизма времени выполнения (virtual
) совсем:
template<typename Derived>
class MyObject {
public:
MyObject() : theRealInstance(static_cast<Derived*>(this)) {
// Check the available interface as soon an instance is created
void (Derived::*op1)(void) = &Derived::methodImpl;
(void)op1;
}
void method() {
theRealInstance->methodImpl();
}
private:
Derived* theRealInstance;
};
struct MyImpl : public MyObject<MyImpl> {
void methodImpl() { std::cout << "method implementation" << std::endl; }
};
struct MyWrongImpl : public MyObject<MyWrongImpl> {
};
void test_alias(){
MyImpl m;
m.method();
// Uncomment to see the compile time error
// MyWrongImpl w;
// w.method();
}
Проверь это рабочий образец.
Вы могли бы даже потребовать method()
реализовать чистый абстрактный интерфейс, но в целом это не обязательно
struct GenericBase {
virtual void method() = 0;
};
template<typename Derived>
class MyObject : public GenericBase {
public:
virtual void method() {
theRealInstance->methodImpl();
}
// Rest as above
};
Вы можете найти немного больше об этой теме и о том, как делать статические проверки интерфейса в этом репозитории GitHub: StaticInterfaces.