Какой-то псевдоним типа: пустой производный класс

Что я хотел бы знать, это:

  • Этот фрагмент переносной?
  • Если нет, то почему?

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, ни шаблоны

1

Решение

Ответ: Это не портативный.

struct MyAlias : public MyObject{
//supposed to have exactly the same layout as MyObject (?)
};

Этот комментарий неверен: размер MyAlias ​​зависит от реализации и не определяется стандартом (это зависит, например, от требований выравнивания целевой архитектуры: компилятор может добавить биты заполнения в производный объект или от того, как метод диспетчеризация осуществляется и т.д ..)

4

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

Этот фрагмент переносной?

Нет, это не портативно. Рассуждать как сказано в @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.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector