一、 vptr && vtable
1、基本上C++传统意义上的多态,就来自vptr和vtable
2、要深入理解,可以参看《深度探索C++对象模型》
3、另一种深入的方式是逆向成汇编,或者编译器把cpp文件生成汇编文件
4、不怕累的话跟调试器也可以
二、 this pointer
没有什么好说的,参照侯老师的ppt应该就可以了
三、 const
1、注意const关键字在定义时候,low-level const还是top-level const,定义的位置不同导致的语义不同
2、const对象和non-const对象对于成员函数调用的规则
3、转载一段文字:(来自https://segmentfault.com/q/1010000002568358/a-1020000002573278)
top-level const : const 修饰的是自身。
low-level const : const 修饰的是别人。
什么叫自身,什么叫别人?C++ 的世界里:
POD,类对象都只能是"自身"
指针可以是自身(指针本身),可以是别人(指向别人)。
引用没有自身,只能是别人。(引用是别名)
所以,有以下几个规律:
指针,可以是 top-level const,也可以是 low-level const。
引用只能是 low-level const。
指针何时是 top-level const,何时是 low-level const,请参考昨天回答的你的另一个问题。
(const char *是 low-level, char * const 是 top-level.)
四、 new/delete重载
1、全局new和delete重载
a、 全局方式重载了new和delete之后,会赢得编译器两个警告,事实上C艹它爸爸在自己书里也有警告:“非特牛逼者勿要重载全局new和delete”。通常麻烦比功能多。
b、 普通的不带参数的全局重载方式
void *operator new(size_t size)
{
//do something……
return malloc(size);
}
void operator delete(void *p)
{
//do something……
free(p);
}
c、 需要注意的是。重载全局的new和delete后,绝大多数class(重载有类成员new和delete的除外)会调用你重载后的版本,会带来许多不可思议的问题。慎重!慎重!慎重!
2、 作为类成员的new和delete
a、只对具体class生效
b、默认情况下,是static的,不需要专门使用static关键字
c、因为是static的成员函数,所以不能使用this指针
d、因为是static的成员函数,所以也无法直接修改object的常规数据成员
e、在static成员函数里要修改object里的数据成员不是不可以,虽然无法直接修改,但是可以通过把object作为参数传递给static函数,进行修改
f、重载方式:
3、 带参数的重载
a、 带参数的重载形式如下:
void *operator new(size_t size, string fuck)
{
cout << "execute --> global fuck new, " << fuck << endl;
return malloc(size);
}
void *operator new[ ] (size_t size, string fuck)
{
cout << "execute --> global fuck new[], " << fuck << endl;
return malloc(size);
}
void operator delete(void *p, string fuck)
{
cout << "execute --> global fuck delete, " << fuck << endl;
free(p);
}
void operator delete[ ] (void *p, string fuck)
{
cout << "execute --> global fuck delete[], " << fuck << endl;
free(p);
}
b、 需要注意,带参数的delete,是在构造函数抛出异常的时候,才会被自动调用。你无法直接调用一个呆参数的delete。
比如,定义一个class:
class theFuck {
int m_;
public:
theFuck(int m = 10) : m_(m)
{
cout << "now, we call theFuck's theFuck(), the object at " << this << endl;
// for call function : void operator delete(void *p, string fuck)
throw std::runtime_error(R"(SOME ERR...)");
}
~theFuck()
{
cout << "now, we call theFuck's ~theFuck(), the object at " << this << endl;
}
};
想看到带参数的delete被执行,你应该在构造里抛出一个异常。
然后这样测试看效果:
void testTheFuck()
{
cout << endl << endl << "------------testTheFuck()------------" << endl;
theFuck *t = nullptr;
try {
t = new("@-@, oh my god!") theFuck();
} catch(std::runtime_error err) {
cout << "we have a exception, it's " << err.what() << endl;
}
if(t!=nullptr) {
cout << "execute --> delete t" << endl;
delete t;
}
cout << endl;
try {
theFuck tfk(100);
} catch(std::runtime_error err) {
cout << "we have a exception, it's " << err.what() << endl;
}
cout << "@-@ : bye bye, testApple()" << endl;
}
4、 new[ ] && delete[ ]
定义方式如new和delete,但是,new[ ] 要配套 delete[ ]
a、 重载方式
void *operator new[ ] (size_t size)
{
//do something……
return malloc(size);
}
void operator delete[ ] (void *p)
{
//do something……
free(p);
}