Skip to content

Instantly share code, notes, and snippets.

@shihongzhi
Created August 24, 2012 02:11
Show Gist options
  • Save shihongzhi/3444738 to your computer and use it in GitHub Desktop.
Save shihongzhi/3444738 to your computer and use it in GitHub Desktop.
在构造函数中调用虚函数
#include "stdafx.h"
using namespace std;
class C180
{
public:
C180() {
foo();
this->foo();
}
virtual void foo() {
//*this == *(void**)this
cout << "<< C180.foo this: " << this << " vtadr: " << *(void**)this << endl;
}
};
class C190 : public C180
{
public:
C190() {}
virtual void foo() {
cout << "<< C190.foo this: " << this << " vtadr: " << *(void**)this << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
C190 obj;
//output:
//<< C180.foo this: " << this << " vtadr: " << *(void**)this
//<< C180.foo this: " << this << " vtadr: " << *(void**)this
obj.foo();
//output:
//"<< C190.foo this: " << this << " vtadr: " << *(void**)this
getchar();
return 0;
}
//标准中提到:这是一种特例,在这种情况下,即在构造子类时调用父类的构造函数,而父类的构造函数中又调用了虚成员函数,这个虚成员函数即使被子类重写,也不允许发生多态的行为。
//因为这种情况下的实例化子类对象是,会先调用父类的构造函数,
//然后父类构造函数申请相应对象的内存空间,得到指向这段内存空间的this指针,同时构建vtable,用vtable point指向刚刚建立的vtable,vtable中写了虚函数C180:foo的指针。
//然后在调用子类的构造函数,因为重载了foo虚函数,所以用指向C190:foo的指针覆盖vtable中虚函数C180:foo的指针, 这样就实现了多态。
//而在父类构造函数中调用虚函数foo时,那是vtable中还是保存着虚函数C180:foo的指针,所以调用的是C180:foo函数。
@shihongzhi
Copy link
Author

C++默认编写并调用的函数是: default构造函数、copy构造函数、析构函数、copy assignment操作符。 唯有当这些函数被调用的时候,它们才会被编译器创建出来。

explicit用于静止隐式转换

为了实现“连续赋值”,令operator=返回一个reference to this:
Widget& operator=(const Widget& rhs)
{
......
return *this
}
此规则最好遵守,同样+=,-=,
=,/=也一样

@shihongzhi
Copy link
Author

class Bitmap {...};

class Widget{
private:
    Bitmap* pb;
}

//自我赋值不安全,并且异常也不安全
Widget& Widget::operator=(const Widget& rhs)
{
    delete pb;
    pb = new Bitmap(*rhs.pb)
    return *this;
}

//自我赋值安全,异常不安全
Widget& Widget::operator=(const Widget& rhs)
{
    if(this == &rhs) return *this;

    delete pb;
    pb = new BItmap(*rhs.pb);
    return *this;
}

//自我赋值安全,并且异常安全
//可以加上这句判断   if(this == &rhs) return *this;
//这个就看情况了,如果自我赋值特别多的话,这句判断语句可以加上。
//如果不多的话,则应该不加,因为这句判断也是需要空间的,并且不加的情况下,自我赋值也是安全的
Widget& Widget::operator=(const Widget& rhs)
{
    Bitmap* pOrig = pb;
    pb = new BItmap(*rhs.pb);
    delete pOrig;
    return *this;
}

//copy and swap技术
class Widget{
void swap(Widget& rhs);     //交换*this和rhs的数据
}

Widget& Widget::operator=(const Widget& rhs)
{
    Widget temp(rhs);
    swap(temp);
    return *this;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment