Подтвердить что ты не робот

Почему явное приведение типов позволяет повысить эффективность для частного наследования?

#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;
}
4b9b3361

Ответ 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 в следующих ситуациях преобразование действительно, даже если базовый класс недоступен:

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

  • [...]

Если вы измените на 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.