vptr和vtbl
只要类里带有虚函数,对象里就会多一个指针。
继承函数是继承函数的调用权,父类有虚函数则子类一定虚函数。
虚指针vptr指向虚表vtbl,虚表中存放虚函数指针。
c++编译器遇到函数调用,有两种方式:静态绑定 动态绑定
静态绑定:call xxx,一定绑定某个确切的地址
动态绑定的三个条件
1. 必须是通过指针调用
2. 指针向上转型
3. 调用的是虚函数。
动态绑定看p指针指向哪儿。
(*(p->vptr)[n])(p)
(* p->vptr[n])(p)
Dynamic Binding
B b;
A a=(A)b;
a.vfunc1();
通过对象调用函数。属于静态绑定,call xxx(xxx为地址)
A* pa=new B;
pa->vfunc1();
满足动态绑定的三个条件,通过指针调用、向上转型、调用的是虚函数
const
const一般只能放在成员函数后,不能加在全局函数之后。
加了const,表示不修改数据。
charT
operator[] (size_type pos) const
{
.../*不必考虑COW*/
}
reference
operator[] (size_type pos)
{
.../*必须考虑COW*/
}
const算作函数的签名
设计共享时,应该考虑数据变化:单独拷贝一份去改。
这两个函数可能被用来改写。所以必须用Copy On Write
调用的是常量字符串,不必做copy on write
当成员函数const和non-const版本同时存在,常量对象只能调用常量版本,非常量对象只会调用非常量版本。
重载全局new new[] delete delete[]
void* myAlloc(size_t size)
{
return malloc(size);
}
void myFree(void *ptr)
{
return free(ptr);
}
inline void* operator new(size_t size)
{
cout<<""<<endl;
return myAlloc(size_t);
}
inline void* operator new[](size_t size)
{
cout<<""<<endl;
return myAlloc(size_t);
}
inline void operator delete(void* ptr)
{
cout<<""<<endl;
return myFree(ptr);
}
inline void operator delete[](void* ptr)
{
cout<<""<<endl;
return myFree(ptr);
}
重载成员new,delete
class Foo{
public:
void* operator new(size_t);
void operator delete(void*,size_t);//第二个参数size_t可有可无
}
Foo* p=new Foo;
分解为:
try{
void* mem=operator new(sizeof(Foo));
p=static_cast<Foo*>(mem);
p->Foo::Foo();
delete p;
分解为
p->Foo();
operator delete(p);