强制类型转换的疑义

强制类型转换的疑问
class A
{
public:
virtual void Print(){cout<<"Class A"<<endl; }
};

class B : public A
{
public:
void Print(){cout<<"Class B"<<endl; }
};

class C : public B
{
public:
void Print(){cout<<"Class C"<<endl; }
void P(int ele){cout<<"Class C element = "<<element<<endl;}
//virtual void P(int ele){cout<<"Class C element = "<<element<<endl;}

private:
int element;
};


int main(int argc, char* argv[])
{
A* pA = new B;
C* pC = (C*)pA;//这个与下面的static_cast没区别吗?
B* pB = static_cast<B*>(pA);

pA->Print();
pB->Print();
pC->Print();
pC->P(10);

system("pause");
return 0;
}


问题:
1、(C*)pA这样的强制类型转换与static_cast没区别吗?
2、pA是指向B类型的指针,为什么pC能够正确调用函数P(int)?怎么找到这个函数的?
强制类型转换的疑义
3、pA是指向B类型的指针,将P(int)定义为virtual类型的函数,程序运行就会报错?
强制类型转换的疑义

------解决方案--------------------
1、(C*)pA这样的强制类型转换与static_cast没区别吗?
这两个应该区别不大,但是这样向下转型很危险,因为有一块数据是不确定的。

2、pA是指向B类型的指针,为什么pC能够正确调用函数P(int)?怎么找到这个函数的?
类中的函数其实是全局的,是所有对象共享的。你可以把它看成一个有this指针作为参数的函数。不同类可以有相同名字的函数因为this指针这个参数不一样,因此是重载。

3、pA是指向B类型的指针,将P(int)定义为virtual类型的函数,程序运行就会报错?
PC指针所指的对象中的vptr其实是PA这个对象的,因此你调这个虚函数的时候当然找不到P这个函数。这也说明了向下转型是危险的

------解决方案--------------------
虚函数 内存布局的时候是通过函数指针来实现
------解决方案--------------------
(C*)pA不会检查
static_cast会检查

pC虽然是指向B类,但是他依然是C类型的,可指向C类中函数

pC中的值是B类的,vptr指向的是B类,B类中没有该虚函数表,没有地址
------解决方案--------------------
因为虚函数是动态绑定的,得看指针指向的对象实际上是什么类型的,你这里pc指的对象实际上是A类型的,所以虚表中的东西都是A的
------解决方案--------------------
我只会复制粘贴混分:强制类型转换的疑义
static_cast、dynamic_cast、reinterpret_cast和const_cast之间的区别
C-style cast举例:
 int i;
 double d;
 i = (int) d;
上面的代码就是本来为double类型的d,通过(int)d将其转换成整形值,并将该值赋给整形变量i (注意d本身的值并没有发生改变)。这就是典型的c-style类型转换。
下面是一个简单的程序:
#include <iostream>
using namespace std;
int main(void)
{
         int i;
         double d = 11.29;
         i = (int)d;
         cout << i << endl;
         cout << d << endl;
         return 0;
}
输出结果:
11
11.29
我们发现d值本身并没有发生任何变化。
在简单的情况下,上面这种类型转换可以很好地工作,但在C++中往往还是不够的,为此ANSI-C++新标准定义的四个转换符,即
     static_cast
    dynamic_cast
reinterpret_cast
      const_cast
同时在C++环境中,原先的C-Style的类型转换仍旧可以使用。
1)  static_cast
    用法:static_cast <typeid> (expression)
    说明:该运算符把expression转换为typeid类型,但没有运行时类型检查来确保转换的安全性。
    用途:
    a) 用于类层次结构中基类和派生类之间指针或者引用的转换。
        up-casting (把派生类的指针或引用转换成基类的指针或者引用表示)是安全的;
        down-casting(把基类指针或引用转换成子类的指针或者引用)是不安全的。
    b) 用于基本数据类型之间的转换,如把int转换成char,这种转换的安全性也要由开发人员来保证。
    c) 可以把空指针转换成目标类型的空指针(null pointer)。
    d) 把任何类型的表达式转换成void类型。
    注意: static_cast不能转换掉expression的const、volitale或者__unaligned属性。
2)  dynamic_cast
    用法:dynamic_cast <typeid> (expression)
    说明:该运算符把expression转换成typeid类型的对象。typeid必须是类的指针、类的引用或者void*。如果typeid是类的指针类型,
        那么expression也必须是指针,如果typeid是一个引用,那么expression也必须是一个引用。一般情况下,dynamic_cast用
        于具有多态性的类(即有虚函数的类)的类型转换。
               dynamic_cast依赖于RTTI信息,其次,在转换时,dynamic_cast会检查转换的source对象是否真的可以转换成target类型,
       这种检查不是语法上的,而是真实情况的检查。先看RTTI相关部分,通常,许多编译器都是通过vtable找到对象的RTTI信息
       的,这也就意味着,如果基类没有虚方法,也就无法判断一个基类指针变量所指对象的真实类型,这时候,dynamic_cast只能
       用来做安全的转换,例如从派生类指针转换成基类指针。而这种转换其实并不需要dynamic_cast参与。也就是说,dynamic_cast
       是根据RTTI记载的信息来判断类型转换是否合法的。
    用途:主要用于类层次之间的up-casting和down-casting,还可以用于类之间的交叉转换。在进行down-casting时,dynamic_cast
        具有类型检查的功能,比static_cast更安全。检测在运行时进行。如果被转换的指针不是一个被请求的有效完整的对象指针,
        返回值为NULL。当用于多态类型时,它允许任意的隐式类型转换以及相反过程。不过,与static_cast不同,在后一种情况里
        (注:即隐式转 换的相反过程),dynamic_cast会检查操作是否有效。也就是说,它会检查转换是否会返回一个被请求的有
        效的完整对象。
    注意:dynamic_cast不能转换掉expression的const、volitale或者__unaligned属性。