Почему явное приведение типов позволяет повысить эффективность для частного наследования?
#include<iostream>
using namespace std;
class A {
public:
void f(){cout<<"A"<<endl;}
};
class B : private A {
public:
void f(){cout<<"B"<<endl;}
};
int main (){
Поскольку класс B наследует класс A в частном порядке, это повышение не должно работать:
A* a = new B;
Но явное приведение типов позволяет.
Почему?
A* a1 = (A*)new B;
a1->f();
return 0;
}
Ответы
Ответ 1
Листинг в
A* a1 = (A*)new B;
- это литой доступ к недоступному базовому классу.
Он может быть выражен только в стиле C. Это эквивалентно тому, что сделал бы static_cast
, если в этой ситуации можно использовать static_cast
, и это не эквивалентно a reinterpret_cast
. В частности, адрес результата не обязательно совпадает с адресом аргумента.
С++ 11 §5.4/4:
" Те же семантические ограничения и поведение [как и для static_cast
] применяются [для создания стиля C], за исключением того, что при выполнении static_cast
в следующих ситуациях конверсия действительно, даже если базовый класс недоступен:
- указатель на объект производного типа класса или lvalue или rvalue типа производного класса может быть явно преобразован в указатель или ссылку на однозначный тип базового класса, соответственно;
Ответ 2
Это разрешено правилами C-style cast:
(N3337) [expr.cast]/4
: Преобразования, выполняемые
- a const_cast (5.2.11),
- static_cast (5.2.9),
- static_cast, за которым следует const_cast,
- a reinterpret_cast (5.2.10) или
- reinterpret_cast, за которым следует const_cast,
может выполняться с использованием буквенного обозначения преобразования явного типа. Те же смысловые ограничения и поведение, , за исключением того, что при выполнении static_cast в следующих ситуациях преобразование действительно, даже если базовый класс недоступен:
Если вы измените на static_cast
, это не скомпилируется. GCC дает эту ошибку:
error: 'A' is an inaccessible base of 'B'
A* a1 = static_cast<A*>(new B);
Ответ 3
Явное кастинг позволяет делать все, что вы хотите. Вы можете, например, написать так:
int *p = (int*)new B;
и код будет скомпилирован.
Явный бросок означает, что вы знаете, что делаете.
Ответ 4
Явное приведение типов - это функция программирования языка C, которая не имеет никаких объектов или правил объектной ориентации. Для языка C все - указатели (в память или функции). Обновление и downcasting - это функции ориентации объектов, предоставляемые С++. Наследование наследования должно вести себя в правилах ориентации объектов на языке. Однако, при типизации объекта следующим образом: A* a1 = (A*)new B;
вы вынуждаете
компилятор обрабатывает объект как A
так же, как и в C, заставляя указатель на структуру другому. Поэтому, когда компилятор решает, какой указатель функции назначить на указателе f()
вызываемого объекта, он присваивает указатель реализации класса A
.