1,默认构造函数:
C++继承机制,按照父类-->子类的流程构造对象,但是如若没有声明构造函数,c++会自动生成默认构造函数,不含形参。
子类的默认构造函数,也是调用父类的默认构造函数。此时如若父类声明了含参的构造函数,调用就会出错。
class Base{
public:
Base()
{
cout<<"Base constructor"<<endl;
}
};
class Derived:public Base{
public:
Derived( )
{
//Base()//查找不到就会出错
//vptr //虚函数指针初始化,记住虚函数的空间浪费
cout<<"Derived constructor"<<endl;
}
};
c++关于默认构造函数的误解:
c++的默认构造函数只会初始化类成员变量,并且还仅仅是调用相关类的默认构造函数,对于常见的指针、int等类型并不会初始化。那些应该是猿的事。
2,拷贝构造:
促发拷贝构造:
X x = y;//注意,单独的x = y会促发赋值构造
fun(X x);//函数调用时,会自动促发
X fun();//函数返回时会自动促发
默认的拷贝构造函数:bitwise:对每个bit施以复制;自己写的拷贝构造函数:memberwise:按项复制。
关于C++虚函数实现机制可以查看博文:C++ 虚函数表解析:http://blog.csdn.net/haoel/article/details/1948051
另外附上完美世界2013年真题一道:
class classA
{
public:
classA()
{
clear();
}
virtual ~classA()
{
}
void clear()
{
memset(this , 0 , sizeof(*this));
}
virtual void func()
{
printf("func\n");
}
};
class classB : public classA
{
};
int main(void)
{
classA oa;
classB ob;
classA * pa0 = &oa;
classA * pa1 = &ob;
classB * pb = &ob;
oa.func(); // 1
ob.func(); // 2
pa0->func(); // 3
pa1->func(); // 4
pb->func(); // 5
return 0;
}
里面3会出core,其他正常:
memset(this , 0 , sizeof(*this));
这句会使得类的虚函数表指针也清空,但是只是清空了父类的,子类并没有清空,所以4和5是正确的;另外对象是无法实现运行时多态的,只有指针(引用)可以,对象在运行虚函数时不用查看虚函数表,和正常函数一视同仁的运行(采用预编译手段,对象类型是确定了,但是指针却不一定,为照顾多态),所以可以正常运行,但是指针就必须查看虚函数表了,以实现多态。详细描述可以参见:http://blog.csdn.net/leeyunfeisblog/article/details/12441873
c++内存中代码数据是按照下图构成的:
其中~Point和print函数为虚函数。
另外,阿波的c++学习笔记(http://blog.csdn.net/livelylittlefish/article/details/2171118)也值得一读,这都是精华,感觉看帖子如同别人输内力给你,但是基础得是你得有好的内功修为,否则真气反扑,浴火焚身。
自己写构造函数:
何时使用初始化列表哪?(亲~,不要告诉我你不知道什么叫初始化列表,如若如此,你还是别读下去了,真气反扑啊)
1,初始化引用成员;2,初始化常量成员;3,调用基类带参的构造函数;4,调用成员类的带参构造函数。
这样不放到{}内,可以节省程序开销,并且3必须放到初始化列表中。
另外注意了,在用初始化列表时,初始化顺序不是列表的顺序,而是在写成员变量时的顺序。