在一下情况中C++会为类自动生成拷贝构造函数
1.类中有虚函数
这种情况即意味着类的对象中有指向虚函数表的指针。考虑下面的情况
class A
{
private:
int m_a;
public:
virtual void ShowVal();
}
void A::ShowVal()
{
printf("%d", m_a);
}
class B
{
private:
int m_b;
public:
void ShowVal();
}
void B::ShowVal()
{
printf("%d", m_b);
}
int main()
{
B b;
b.m_b = 10;
A a = b; //此处应该会有拷贝构造函数的调用(如果有)
A* pa = &a;
pa->ShowVal();
}
pa->ShowVal会报错吗?不会,但是是在编译器参与纠正的情况下,否则就错了。
因为A类的ShowVal是虚函数,也就导致A类是有虚函数表的,该表中有A类的ShowVal函数的地址,A类的ShowVal函数显示A类成员m_a
而B类继承A类后,由于B类重写了A类的ShowVal,显示B类成员m_b。因此,B类的虚函数表中存放了B类的ShowVal的地址,而不是A类的ShowVal的地址。
因此,通过简单的位拷贝模式(不提供拷贝构造函数的情况下,是默认使用位拷贝的模式),直接将B类的vptr拷贝到A类对象中。然后,当通过指针调用该A类对象的ShowVal函数的时候,就会访问到B类虚函数表中的ShowVal函数,访问到B类的m_b成员(不存在于A类对象中),然后就会出错了。
因此,编译器需要查收进行虚函数表的调整,会自动给A类生成一个拷贝构造函数,函数中重新设置A类对象的vptr,大致如下:
A::A(const A& a)
{
this->vptr=A类的虚函数表地址;
}
那么,如果程序员显示提供了A类的构造函数的情况下会发生什么,编译器还会自动生成拷贝构造函数吗?
当A类有虚函数且程序员提供了拷贝构造函数的时候,程序员提供的拷贝构造函数肯定也不会去写重新设置vptr代码,因此,编译器会在程序员提供的拷贝构造函数中添加设置vptr的代码。
2.基类包含拷贝构造函数或者成员变量的类提供了拷贝构造函数
无论是程序员提供的拷贝构造函数还是像第一中情况下编译器自动生成的拷贝构造函数,只要基类包含了拷贝构造函数,就说明派生类中的基类部分不能直接使用位拷贝的模式进行赋值,必须调用所提供的拷贝构造函数就行构造,此时编译器会生成拷贝构造函数
B::B(const B& b)
{
this->A::A(b);
}
类中的成员变量的类提供了构造函数的情况也是一样的
B::B(const B&b)
{
this->m_a.A::A(b.m_a);
}