Могу ли я привести производный класс к закрытому базовому классу, используя приведение в стиле C?

Я могу это сделать?

class A { ... };

class B : private A
{
const A &foo() const
{
return *((const A *)this);
}
};

Могу ли я взять подкласс, который наследуется в частном порядке от базового класса, и привести его к публичной версии его базового класса? Могу ли я сделать это без виртуальных методов?

Я думаю, да, но я хотел убедиться, что это безопасно / портативно.

17

Решение

Да, вы можете: §5.4 / 7 стандарта:

… следующие операции static_cast и reinterpret_cast
(необязательно сопровождаемый операцией const_cast) может быть выполнен с использованием
приведенная нотация явного преобразования типов, даже если базовый класс
тип не доступен:

указатель на объект производного класса или lvalue производного
Тип класса может быть явно преобразован в указатель или ссылку на
однозначный тип базового класса соответственно;

Но попробуй не поскольку это побеждает цель частного наследства.

15

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

Да, это явно разрешено. Александреску широко использует это в Современный дизайн C ++ за его подход к разработке политики на основе политики:

template <typename Policy>
class foo : Policy
{
public:
void do_something()
{
Policy & p = *this;
p.do_something();
}
};

Таким образом, хотя варианты использования могут быть ограничены, есть некоторые из них.

8

Исходя из названия вопроса, ответ зависит. Но для вашего случая в вашем исходном коде ответ — да.

Есть два фактора, которые будут влиять на ответ:

  1. Если вы используете приведение в стиле C, произойдет да, потому что приведение вызовет повторное преобразование, если преобразование недоступно. Вы можете привести любой тип указателя к целевому типу указателя. Но если есть MI, результат может быть неправильным для большинства реализаций языка C ++.

  2. Если вы выполняете приведение (без преобразования в стиле C) внутри функции memeber, ответ будет «да», потому что базовый класс доступен внутри функции-члена. Если выражение находится в месте, где базовый класс недоступен, вы получите ошибку компиляции.

Более подробно о стандартном общении в стандарте C ++

A prvalue of type “pointer to cv D”, where D is a class type, can be converted to a prvalue of type “pointer to cv B”, where B is a base class (Clause 10) of D.
If B is an inaccessible (Clause 11) or ambiguous (10.2) base class of D, a program that necessitates this conversion is ill-formed.
The result of the conversion is a pointer to the base class subobject of the derived class object. The null pointer value is converted to the null pointer value of the destination type.

Редактировать 2: сделать ответ более подробно.

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