一:拷贝构造函数语义
1.如果没有定义一个自己的拷贝构造函数,编译器会帮助我们生成一个拷贝构造函数
2.这个拷贝构造函数也是在必要的时候才会被编译器合成
class A{
public:
int m;
};
int main(){
A a;
a.m = 14;
A a2 = a; // 调用拷贝构造函数? no
// 按照之前的操作输出my.txt(对象模型3), 并没有拷贝构造函数
// 这里其实我觉得是相同的class的各个objects互为friends;
// 所以这里没有必要创建拷贝构造函数
}
二: 相同的class的各个objects互为friends的一点思考
class Complex{
public:
complex(double r = 0, double i = 0):re(r), im(i){}
int func(const comple& param){
return param.re + param.im; // private re im。
}
private:
double re, im;
};
int main(){
complex c1(1,2);
complex c2;
c2.fimc(c1);
}
// 这个代码已经很好的证明了相同的class的各个objects互为friends
// 没有破坏封装性
三: 编译器合成拷贝构造函数1
1.如果类A没有拷贝构造函数,但是类有一个类类型的成员变量,该类型含有拷贝构造函数,那么
当代码中设计到类A的拷贝构造时,编译器就会为类A合成一个拷贝构造函数
class A{
public:
A(const A&){} // 拷贝构造函数
A(){}
};
class B{
public:
int a;
A a;
};
int main(){
B b1;
b1.a = 3;
B b2 = b1;
}
// 这个合成的构造函数 直会去调用类A的构造函数,
// 编译器合成的拷贝构造函数往往都是干一些特殊的事情
四: 编译器合成拷贝构造函数2
1.如果一个子类没有拷贝构造函数,但是它有一个父类,父类有拷贝构造函数
// 当代码中有涉及子类的拷贝构造时,编译器会为子类合成一个拷贝构造函数
class A{
public:
A(const int&){}
A(){}
};
class B:public A{
public:
}
int main(){
B b1;
B b2 = b1;
}
五: 编译器合成拷贝构造函数3
1.如果一个类没有拷贝构造函数,但是该类声明了或者继承了虚函数
// 当代码中有涉及子类的拷贝构造时,编译器会为子类合成一个拷贝构造函数
class A{
public:
virtual void virtualFunc(){}
};
int main(){
A a1;
A a2 = a1;
}
// 这里生成的拷贝构造函数 主要功能就是vftable 也就是将a1虚函数表将首地址赋值给a2的虚指针
class A{
public:
virtual void virtualFunc(){}
};
class B : public A{
public:
}
int main(){
A a1;
A a2 = a1;
}
//这里也会生成一个拷贝构造函数。 首先 父类A有虚函数会先生成一个拷贝构造函数
// 然后类B会继承类A 所以类B也有一个虚函数 , 所以类B也会合成一个拷贝构造函数
// 这个拷贝构造函数先调用父类的拷贝构造函数 然后也是将虚函数表首地址赋值给a1
六: 编译器合成拷贝构造函数4
1.如果一个类没有拷贝构造函数,但是该类含有虚基类
// 当代码中有涉及子类的拷贝构造时,编译器会为子类合成一个拷贝构造函数
class Grand{
public:
}
class A1 : virtual public Grand{
public:
}
class A2 : vlrtual public Grand{
public:
}
public C : public A1, public A2{
public:
}
int main(){
C cc;
C cc2 = cc; // 虚基类表 vbtable
}