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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述