kwseeker

学编程:找代码,读代码,改代码,写代码;少看书。但少看不是不看,看一本书要限制在一天内。任务是通读书中主要的概念,明白大致是干什么用的,形成一个大概的框架;然后一周内干掉书中全部代码,代码不理解再浏览书中相关章节,注意是浏览。或者刷博客。代码实在刷不懂,可以先刷后面,待日后重新刷;因为书中代码有些部分可能出自后面的章节。代码总是在多次刷过之后,拨开乌云见日月的。。。

导航

C++@子类类型转换为父类类型

static_cast(*this) to a base class create a temporary copy.

class Window {                                 // base class
public:
  virtual void onResize() { ... }              // base onResize impl
  ...
};

class SpecialWindow: public Window {          // derived class
public:
  virtual void onResize() {                   // derived onResize impl;
  static_cast<Window>(*this).onResize();      // cast *this to Window,
                                              // then call its onResize;
                                              // this doesn't work!
    ...                                       // do SpecialWindow-
  }                                           // specific stuff

  ...

};        

Effective C++: What you might not expect is that it does not invoke that function on the current object! Instead, the cast creates a new, temporary copy of the base class part of *this, then invokes onResize on the copy! 

*******************************************************************************************

Contrast:

static_cast<Window>(*this)

with:

static_cast<Window&>(*this)

One calls the copy constructor, the other does not. 

*******************************************************************************************

Because you are casting actual object not a pointer or reference. It's just the same with casting double to int creates new int - not reusing the part of double.

double类型转换为int型会创建一个新的int型变量?

*******************************************************************************************

上面的句子static_cast<Window>(*this).onResize();千万别改成下面这样,那样会更悲惨!

  virtual void onResize()
    {
        static_cast<Window*>(this)->onResize(); //调用基类的onResize()
        derived_ = 2;
        std::cout <<"S" << " base_=" << base_ << ",derived=" << derived_ << std::endl;
    }

实际上,可能只有C的高手初转C++,对C++对象的内存模型还不很清楚的情况下才会写成这样的代码。

对一个指针,不论我们怎样强制转换,它指向的那段内存的内容并没有改变。
函数把本类对象的指针强制转换为基类对象的指针,只意味着“通过这个指针只能访问基类的成员”了,而对象的内容并没有改变。onResize是虚函数,调用它是先通过对象中指向虚表的指针找到虚表,然后在虚表中找到onResize函数的指针,最后通过函数指针调用函数。  this指针强制转换后,内存没有改变,所以指向虚表的指针没有改变,所以它找到的虚表仍是派生类的虚表,自然找到的函数指针仍是派生类的onResize函数的指针,所以这里就成了一个无穷递归调用,结果就是消耗完栈空间。

将函数修改为这样:你就会看到不断的输出ReCall.
    virtual void onResize()
    {
        std::cout<<"ReCall"<<endl;
        static_cast<Window*>(this)->onResize(); //调用基类的onResize()
        derived_ = 2;
        std::cout <<"S" << " base_=" << base_ << ",derived=" << derived_ << std::endl;
    }

posted on 2015-06-07 22:43  kwseeker  阅读(1618)  评论(1编辑  收藏  举报