为什么显式类型转换允许向上转换私有继承?

时间:2016-03-31 08:02:03

标签: c++

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

4 个答案:

答案 0 :(得分:18)

演员

A* a1 = (A*)new B;

是对无法访问的基类的强制转换。

它只能表示为C样式转换。它相当于static_cast在这种情况下可以使用static_cast时所做的事情,并且它不等同于reinterpret_cast。特别是结果地址不一定与参数地址相同。

C ++11§5.4/ 4:
  

相同的语义限制和行为[与static_cast]相同[适用于C样式演员],但在执行static_cast时除外在以下情况下,即使基类不可访问,转换也是有效的:

     

- 指向派生类类型的对象或派生类类型的左值或右值的指针可以分别显式转换为指针或对明确基类类型的引用;

答案 1 :(得分:8)

这是C风格演员表的规则所允许的:

  

(N3337)[expr.cast]/4:由

执行的转换      
      
  • 一个const_cast(5.2.11),
  •   
  • 一个static_cast(5.2.9),
  •   
  • 一个static_cast,后跟一个const_cast,
  •   
  • 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);

答案 2 :(得分:5)

显式投射可让您完成所需的一切。例如,您可以这样写:

int *p = (int*)new B; 

并编译代码。 明确的演员表示你知道自己在做什么。

答案 3 :(得分:1)

显式类型转换是C语言的编程功能,它没有任何面向对象的功能或规则。对于C语言,一切都是指针(对内存或函数)。 Updcasting和向下转换是c ++提供的面向对象功能。继承强制转换必须符合语言的面向对象规则。但是,通过对类似对象进行类型转换:A* a1 = (A*)new B; 编译器将对象视为A,就像在C中强制将结构的指针强制转换为另一个一样。因此,当编译器决定在转换对象的f()调用指针上分配哪个函数指针时,它会分配A类实现的指针。