Могу ли я привести производный класс к закрытому базовому классу, используя приведение в стиле C?
Я могу это сделать?
class A { ... };
class B : private A
{
const A &foo() const
{
return *((const A *)this);
}
};
Могу ли я взять подкласс, который наследуется в частном порядке от базового класса, и привести его к публичной версии его базового класса? Могу ли я сделать это без виртуальных методов?
Я думаю, да, но я хотел убедиться, что это безопасно / портативно.
3 ответа
Да, вы можете: §5.4/7 стандарта:
... следующие операции static_cast и reinterpret_cast (необязательно сопровождаемые операцией const_cast) могут быть выполнены с использованием записи преобразования явного преобразования типа, даже если тип базового класса недоступен:
указатель на объект типа производного класса или значение l типа производного класса может быть явно преобразован в указатель или ссылку на однозначный тип базового класса соответственно;
Но старайтесь не делать этого, поскольку это побеждает цель частного наследства.
Да, это явно разрешено. Александреску широко использует это в Modern C++ Design для своего подхода к разработке на основе политик:
template <typename Policy>
class foo : Policy
{
public:
void do_something()
{
Policy & p = *this;
p.do_something();
}
};
Так что, хотя варианты использования могут быть ограничены, есть некоторые из них.
Исходя из названия вопроса, ответ зависит. Но для вашего случая в вашем исходном коде ответ - да.
Есть два фактора, которые будут влиять на ответ:
Если вы используете приведение в стиле C, произойдет да, потому что приведение вызовет повторное преобразование, если преобразование недоступно. Вы можете привести любой тип указателя к целевому типу указателя. Но если есть MI, результат может быть неправильным для большинства реализаций языка C++.
Если вы выполняете приведение (без преобразования в стиле 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: сделать ответ более подробно.