Могу ли я привести производный класс к закрытому базовому классу, используя приведение в стиле 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();
        }
};

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

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

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

  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: сделать ответ более подробно.

Другие вопросы по тегам