第2章构造函数语意学
来源:互联网 发布:海量数据处理 java 编辑:程序博客网 时间:2024/05/15 17:11
2.1Default Constructor的建构操作
“default constructors在需要的时候被编译器产生出来”
程序的需要和编译器的需要。
程序的需要,是程序员的责任。
当编译需要的时候,才会合成出来default constructor。被合成出来的constructor只执行编译器所需要的行动。
"对于class X,如果没有任何user-declared-constructor,那么会有一个default constructor被暗中(implicitly)声明出来......一个被暗中声明出来的default constructor将是一个trivial constructor"
举例:
//test.cpp
class Foo{
public:
int val;
Foo * pnext;
};
int main(){
Foo myFoo;
return 0;
}
// 反汇编
objdump -dC test.o
// 输出内容
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:83 ec 10 sub $0x10,%esp
6:b8 00 00 00 00 mov $0x0,%eax
b:c9 leave
c:c3 ret
// 可以看到没有产生default constructor
nontrivial default constructor
1."带有default constructor"的member class object
如果一个class没有任何constructor,但它内含一个member object,而后者有default constructo,那么这个class的implicit default constructor就是“nontrivial”,编译器需要为此class合成一个default construtor
举例:
//test.cpp
class Foo{
public:
Foo();
int val;
Foo * pnext;
};
Foo::Foo(){
}
class Bar{
public:
Foo foo;
char *str;
};
int main(){
Bar myBar;
return 0;
}
//反汇编
objdump -dC test.o
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <Foo::Foo()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:5d pop %ebp
4:c3 ret
00000005 <main>:
5:55 push %ebp
6:89 e5 mov %esp,%ebp
8:83 e4 f0 and $0xfffffff0,%esp
b:83 ec 20 sub $0x20,%esp
e:8d 44 24 14 lea 0x14(%esp),%eax
12:89 04 24 mov %eax,(%esp)
15:e8 fc ff ff ff call 16 <main+0x11>
1a:b8 00 00 00 00 mov $0x0,%eax
1f:c9 leave
20:c3 ret
Disassembly of section .text._ZN3BarC2Ev:
00000000 <Bar::Bar()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:83 ec 04 sub $0x4,%esp
6:8b 45 08 mov 0x8(%ebp),%eax
9:89 04 24 mov %eax,(%esp)
c:e8 fc ff ff ff call d <Bar::Bar()+0xd>
11:c9 leave
12:c3 ret
class的default constructor会依次序调用成员object的constructor
“如果class A内含一个或一个以上的member class objects,那么class A的每一个constructor必须调用每一个member classes的default constructor”
2."带有default constructor的"base class
如果一个没有任何constructor的class派生自一个“带有default constructor”的base class,那么这个derived class的default constructor会被视为nontrivial,并因此需要被合成出来。它将调用上一层base classes的defualt constructor。对一个后续派生的class而言,这个合成的constructor和一个“被明确提供的default constructor"没有什么差异。
//test.cpp
class Foo{
public:
Foo();
int val;
Foo * pnext;
};
Foo::Foo(){
}
class Bar: public Foo{
public:
char *str;
};
int main(){
Bar myBar;
return 0;
}
//反汇编
objdump -dC test.o
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <Foo::Foo()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:5d pop %ebp
4:c3 ret
00000005 <main>:
5:55 push %ebp
6:89 e5 mov %esp,%ebp
8:83 e4 f0 and $0xfffffff0,%esp
b:83 ec 20 sub $0x20,%esp
e:8d 44 24 14 lea 0x14(%esp),%eax
12:89 04 24 mov %eax,(%esp)
15:e8 fc ff ff ff call 16 <main+0x11>
1a:b8 00 00 00 00 mov $0x0,%eax
1f:c9 leave
20:c3 ret
Disassembly of section .text._ZN3BarC2Ev:
00000000 <Bar::Bar()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:83 ec 04 sub $0x4,%esp
6:8b 45 08 mov 0x8(%ebp),%eax
9:89 04 24 mov %eax,(%esp)
c:e8 fc ff ff ff call d <Bar::Bar()+0xd>
11:c9 leave
12:c3 ret
4."带有一个virtual function"的class
同理
class Widget{
public:
virtual void flip() = 0;
};
class Bell:public Widget{
public:
virtual void flip();
};
void Bell::flip(){}
class Whistle:public Widget{
public:
virtual void flip();
};
void Whistle::flip(){}
int main(){
Bell mybell;
Whistle mywhistle;
return 0;
}
//反汇编
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <Bell::flip()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:5d pop %ebp
4:c3 ret
5:90 nop
00000006 <Whistle::flip()>:
6:55 push %ebp
7:89 e5 mov %esp,%ebp
9:5d pop %ebp
a:c3 ret
0000000b <main>:
b:55 push %ebp
c:89 e5 mov %esp,%ebp
e:83 e4 f0 and $0xfffffff0,%esp
11:83 ec 20 sub $0x20,%esp
14:8d 44 24 1c lea 0x1c(%esp),%eax
18:89 04 24 mov %eax,(%esp)
1b:e8 fc ff ff ff call 1c <main+0x11>
20:8d 44 24 18 lea 0x18(%esp),%eax
24:89 04 24 mov %eax,(%esp)
27:e8 fc ff ff ff call 28 <main+0x1d>
2c:b8 00 00 00 00 mov $0x0,%eax
31:c9 leave
32:c3 ret
Disassembly of section .text._ZN6WidgetC2Ev:
00000000 <Widget::Widget()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:8b 45 08 mov 0x8(%ebp),%eax
6:c7 00 08 00 00 00 movl $0x8,(%eax)
c:5d pop %ebp
d:c3 ret
Disassembly of section .text._ZN4BellC2Ev:
00000000 <Bell::Bell()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:83 ec 18 sub $0x18,%esp
6:8b 45 08 mov 0x8(%ebp),%eax
9:89 04 24 mov %eax,(%esp)
c:e8 fc ff ff ff call d <Bell::Bell()+0xd>
11:8b 45 08 mov 0x8(%ebp),%eax
14:c7 00 08 00 00 00 movl $0x8,(%eax)
1a:c9 leave
1b:c3 ret
Disassembly of section .text._ZN7WhistleC2Ev:
00000000 <Whistle::Whistle()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:83 ec 18 sub $0x18,%esp
6:8b 45 08 mov 0x8(%ebp),%eax
9:89 04 24 mov %eax,(%esp)
c:e8 fc ff ff ff call d <Whistle::Whistle()+0xd>
11:8b 45 08 mov 0x8(%ebp),%eax
14:c7 00 08 00 00 00 movl $0x8,(%eax)
1a:c9 leave
1b:c3 ret
//但是如果不掉用Bell,Whister
int main(){
//Bell mybell;
//Whistle mywhistle;
return 0;
}
//反汇编
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <Bell::flip()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:5d pop %ebp
4:c3 ret
5:90 nop
00000006 <Whistle::flip()>:
6:55 push %ebp
7:89 e5 mov %esp,%ebp
9:5d pop %ebp
a:c3 ret
0000000b <main>:
b:55 push %ebp
c:89 e5 mov %esp,%ebp
e:b8 00 00 00 00 mov $0x0,%eax
13:5d pop %ebp
14:c3 ret
没有出现任何构造函数,只有需要的时候才会构造
一个virtual function table会被编译器产生出来,内放class的virtual functions地址。
在每一个class object中,一个额外的pointer member会被编译器合成出来,内含相关的class vtbl的地址。
对于那些未声明任何constructor的classes,编译器会为它们合成一个default constructor,以便正确地初始化每一个class object的vptr
4."带有一个virtual base class"的class
//test.cpp
class X{
public:
int i;
};
class A:public virtual X{
public:
int j;
};
class B:public virtual X{
public:
double d;
};
class C:public A, public B{
public:
int k;
};
void foo(A* pa){
pa->i = 1024;
}
int main(){
foo(new A);
foo(new C);
return 0;
}
//反汇编
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <foo(A*)>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:8b 55 08 mov 0x8(%ebp),%edx
6:8b 45 08 mov 0x8(%ebp),%eax
9:8b 00 mov (%eax),%eax
b:83 e8 0c sub $0xc,%eax
e:8b 00 mov (%eax),%eax
10:8d 04 02 lea (%edx,%eax,1),%eax
13:c7 00 00 04 00 00 movl $0x400,(%eax)
19:5d pop %ebp
1a:c3 ret
0000001b <main>:
1b:55 push %ebp
1c:89 e5 mov %esp,%ebp
1e:83 e4 f0 and $0xfffffff0,%esp
21:53 push %ebx
22:83 ec 1c sub $0x1c,%esp
25:c7 04 24 0c 00 00 00 movl $0xc,(%esp)
2c:e8 fc ff ff ff call 2d <main+0x12>
31:89 c3 mov %eax,%ebx
33:89 d8 mov %ebx,%eax
35:89 04 24 mov %eax,(%esp)
38:e8 fc ff ff ff call 39 <main+0x1e>
3d:89 d8 mov %ebx,%eax
3f:89 04 24 mov %eax,(%esp)
42:e8 fc ff ff ff call 43 <main+0x28>
47:c7 04 24 1c 00 00 00 movl $0x1c,(%esp)
4e:e8 fc ff ff ff call 4f <main+0x34>
53:89 c3 mov %eax,%ebx
55:89 d8 mov %ebx,%eax
57:89 04 24 mov %eax,(%esp)
5a:e8 fc ff ff ff call 5b <main+0x40>
5f:89 d8 mov %ebx,%eax
61:89 04 24 mov %eax,(%esp)
64:e8 fc ff ff ff call 65 <main+0x4a>
69:b8 00 00 00 00 mov $0x0,%eax
6e:83 c4 1c add $0x1c,%esp
71:5b pop %ebx
72:89 ec mov %ebp,%esp
74:5d pop %ebp
75:c3 ret
Disassembly of section .text._ZN1XC2Ev:
00000000 <X::X()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:5d pop %ebp
4:c3 ret
Disassembly of section .text._ZN1AC2Ev:
00000000 <A::A()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:8b 45 0c mov 0xc(%ebp),%eax
6:8b 00 mov (%eax),%eax
8:89 c2 mov %eax,%edx
a:8b 45 08 mov 0x8(%ebp),%eax
d:89 10 mov %edx,(%eax)
f:5d pop %ebp
10:c3 ret
Disassembly of section .text._ZN1AC1Ev:
00000000 <A::A()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:83 ec 18 sub $0x18,%esp
6:8b 45 08 mov 0x8(%ebp),%eax
9:83 c0 08 add $0x8,%eax
c:89 04 24 mov %eax,(%esp)
f:e8 fc ff ff ff call 10 <A::A()+0x10>
14:b8 00 00 00 00 mov $0x0,%eax
19:8d 50 0c lea 0xc(%eax),%edx
1c:8b 45 08 mov 0x8(%ebp),%eax
1f:89 10 mov %edx,(%eax)
21:c9 leave
22:c3 ret
Disassembly of section .text._ZN1BC2Ev:
00000000 <B::B()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:8b 45 0c mov 0xc(%ebp),%eax
6:8b 00 mov (%eax),%eax
8:89 c2 mov %eax,%edx
a:8b 45 08 mov 0x8(%ebp),%eax
d:89 10 mov %edx,(%eax)
f:5d pop %ebp
10:c3 ret
Disassembly of section .text._ZN1CC1Ev:
00000000 <C::C()>:
0:55 push %ebp
1:89 e5 mov %esp,%ebp
3:83 ec 18 sub $0x18,%esp
6:8b 45 08 mov 0x8(%ebp),%eax
9:83 c0 18 add $0x18,%eax
c:89 04 24 mov %eax,(%esp)
f:e8 fc ff ff ff call 10 <C::C()+0x10>
14:b8 00 00 00 00 mov $0x0,%eax
19:8d 50 04 lea 0x4(%eax),%edx
1c:8b 45 08 mov 0x8(%ebp),%eax
1f:89 54 24 04 mov %edx,0x4(%esp)
23:89 04 24 mov %eax,(%esp)
26:e8 fc ff ff ff call 27 <C::C()+0x27>
2b:b8 00 00 00 00 mov $0x0,%eax
30:8d 50 08 lea 0x8(%eax),%edx
33:8b 45 08 mov 0x8(%ebp),%eax
36:83 c0 08 add $0x8,%eax
39:89 54 24 04 mov %edx,0x4(%esp)
3d:89 04 24 mov %eax,(%esp)
40:e8 fc ff ff ff call 41 <C::C()+0x41>
45:ba 0c 00 00 00 mov $0xc,%edx
4a:8b 45 08 mov 0x8(%ebp),%eax
4d:89 10 mov %edx,(%eax)
4f:b8 00 00 00 00 mov $0x0,%eax
54:8d 50 18 lea 0x18(%eax),%edx
57:8b 45 08 mov 0x8(%ebp),%eax
5a:89 50 08 mov %edx,0x8(%eax)
5d:c9 leave
5e:c3 ret
pa不能确定x::i的位置,只能在执行期决定。
在derived class object的每一个virtual base classed 中安插一个指针完成。
_vbcX是在class object建构期间完成的,对于与class所定义的每一个constructor,编译器会安插那些“允许每一个virtual base class的执行期存取操作”的码,如果class没有声明任何constructors,编译器必须为它合成一个default constructor
- 第2章构造函数语意学
- 构造函数语意学
- 第2章 构造函数语意学-《深度探索C++对象模型》读书笔记
- 《深度探索C++对象模型》- 第2章 构造函数语意学
- 【深度探索C++对象模型读书笔记】【第2章】构造函数语意学
- 第二章 构造函数语意学
- Chap2-构造函数语意学
- 构造函数之语意学
- 第5章 构造、结构、拷贝、语意学
- 构造函数语意学和Data语意学
- 构造函数语意学----程序转化语意学
- C++对象模型 第二章 构造函数语意学
- 深度探索C++对象模型 2构造函数语意学
- 《深度探索C++对象模型》--2 构造函数语意学
- 构造函数语意学----初始化列表
- 构造函数语意学 笔记(一)
- 构造函数语意学 笔记(二)
- 构造函数语意学 笔记(三)
- Android之父Andy Rubin:被乔布斯羡慕嫉妒的天才
- Android浏览器Browser二次开发(四)浏览器中的APN切换
- X264 在VC中编译问题补充-日志!
- 我国电子政务发展模式初探【转】
- ftp的使用若干问题
- 第2章构造函数语意学
- delphi xe编译报Unit not found: 'System.pas' or binary equivalents 的解决办法
- 码率、比特率、采样率
- js获得浏览器高度和宽度 参数
- 使用sqlAlchemy和mysqldb时unicode的设置问题
- USB接口IC读写器oem软件_AB密码完整解决方案/读写卡测试程序及源代码/VB源代码
- ACE多线程编程
- 在MFC下如何定义全局变量
- Android自定义控件及按下效果