C++ 对象模型学习记录(1)--- 第2章 构造函数语义学
1.
#include <iostream>
using namespace std;
class Foo
{
public:
Foo(),Foo(int);
};
//这里被合成的Bar default 构造函数内含有member
//object,foo拥有default constructor,所以会初始化Bar::foo()
//但是初始化str 的责任是程序员的,即编译器不会初始化str
class Bar
{
public:
Foo foo;//内含
char *str;
};
void foo_bar()
{
Bar bar;
}
int main()
{
cout << "Hello world!" << endl;
return 0;
}
上述代码中的bar 可能会被转化为
Bar::Bar()
{
//伪码
foo.Foo()::Foo()
}
而被合成的default constructor 只满足编译器的需要,不满足程序的需要,要是程序正确,还必须将str初始化
Bar :: Bar(){str = 0;} ,有了这个自定义的构造函数,编译器没法合成第2个了,这时,编译器采取:
“如果class A 内含有一个或者一个以上的member object” ,那么class A 的每一个constructor都必须调用每一个member classes 的default constructor
如果有多个 member object,编译器以声明他们的顺序完成初始化
2 有4种情况,编译器会为 未声明的constructor 的class合成一个default 构造函数
(1) 如果一个class没有任何的constructor,但是它内含有一个member object,而这个成员object有默认的构造函数,那么这个类的implicit的default constructor就是nontrivial的,编译器会合成一个default 构造函数,不过这个默认构造函数仅仅在需要的时候合成
如何避免合成多个default 构造函数? 编译器使用inline函数。
实际上,default constructor,default destructor,assignment copy operator都是以内联的方式完成的,内联函数是静态链接的
(2)带有 default 构造函数的 base class 基类
如果没有任何constructor的class继承自一个“带有构造函数的类”,那个这个drived class子类的默认构造函数会被视为一个nontrivial,被合成出来,如果在子类中定义了多个构造函数,但是没有一个使用base类 的 default构造函数,编译器会扩展子类的每一个构造函数
(3) 带有virtual 函数的 class
class 声明为(或者继承自)一个virtual 函数
class派生自一个继承串链,其中有一个或者多个virtual 函数
(4) 带有一个虚基类的class
两种误解
1. 任何class ,如果没有定义默认构造函数,编译器会自动创建一个
2. 编译器合成出来的default构造函数会明确的设定class内的每一个data member的默认值
编译器只会设置对编译必须的值,而其他的默认值必须由程序员自己初始化
#include <iostream>
using namespace std;
class String
{
//类中没有显示的提供copy构造函数
public:
String(string name)
{
str = name;
}
string getStr()
{
return str;
}
private :
string str;
};
int main()
{
String noun("book");
String verb = noun;
cout << verb.getStr() << endl;
return 0;
}
3. copy 构造函数建构的3种情况
1. 对一个类做明确的初始化操作
2. 当作函数的形参时
3. 当一个函数的返回值(回传一个对象)
另外,如果么有显示的实现copy构造函数,编译器使用所谓的default memberwise initializator 手法,将一个内建的data member从一个object拷贝到另一个object中,不过不会拷贝member class object,对他们则是递归的使用default memberwise initializator 手法
一个错误的认识:
对于未定义拷贝构造函数的类,编译器会自动实现一个copy拷贝构造函数
c ++ Standard 将copy 构造函数分为 nontrivial 和 trivial,只有nontrivial的才会被合成到程序之中
而是不是trivial的,取决于 class 是不是展现出 bitwise copy semantics(位逐次拷贝)
4 .什么时候class不展现位逐次拷贝
1. 当class内含有一个member class object,而这个member class 内有一个默认的copy 构造函数
2. 当class 继承自 一个base class,而bese class 有copy构造函数
3. 当一个类声明了多个virtual 函数
4. 当class派生自一个继承串链,其中一个或者多个virtual base class