Допустимость приведения указателя Base к производному указателю, когда в Derived добавляются только методы

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

class Base { /* ... */ };

class Derived : public Base
{
public:
void additionnalFunc(int i){ /* access Base members */ }
};

int main(){
Base b;
Derived* d = (Derived*) &b; // or static_cast ?
d->additionnalFunc(3); // works ok.
}

Это работает, как и ожидалось с GCC. Итак, мой вопрос, это безопасно / действительно? с любым компилятором или архитектурой? если нет, то почему?

Чтобы объяснить, почему этот вопрос, вот контекст.

  • У меня есть «базовые» объекты.
  • Я не могу изменить Базовый класс
  • У меня есть набор шаблонных функций, который требует того же интерфейса
    в качестве базы, за исключением нескольких дополнительных функций.
  • Я хочу иметь возможность использовать эту шаблонную библиотеку с моими базовыми объектами
  • Из-за дополнительных функций вышеперечисленное невозможно. Но
    эти функции тривиальны для реализации из базы.
  • Также я хочу быть максимально эффективным (избегать конверсий и
    indirections)

Так что, если приведенный выше трюк действителен, это может быть хорошим решением … Но, может быть, есть лучший дизайн для решения этой проблемы?

2

Решение

Это неопределенное поведение. «Работает» ли это на каком-либо конкретном компиляторе, возможно, не в этом дело; Вы не можете полагаться на эту работу в целом.*

В описанном вами сценарии кажется, что лучшим решением будет просто создать несколько бесплатных функций, которые Base в качестве аргумента. Конечно, если требуемая функциональность зависит от protected участники, тогда у вас есть проблемы! (И я не уверен, что есть хорошее решение, кроме как найти способ избежать такого доступа.)


* И это правда, даже если вы никогда не меняете свой компилятор. Компилятор может предположить, что весь код «правильный», поэтому небольшое изменение в вашем коде может вызвать оптимизацию, которая сделает вышеуказанный трюк бесполезным.

(Конечно, я не собираюсь предполагать, что это будет определенно случиться только потому, что это мог.)

2

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

Других решений пока нет …

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