文章目录
前言
构造函数(也叫构造器),在对象创建的时候自动调用,一般用于完成对象的初始化工作
构造函数与类同名,无返回值(void都不用写),可以由参数,可以重载,可以有多个构造函数
一旦自定义了构造函数,必须用其中一个自定义的构造函数来初始化对象
无参的构造函数
#include <iostream>
using namespace std;
class Person {
private:
int m_age;
int m_height;
public:
Person() {
cout << "无参构造函数:Person()" << endl;
cout << "age=" << m_age << ",height=" << m_height << endl;
}
};
int main() {
//栈空间
Person person;
Person person2;
Person person3;
return 0;
}
out为
无参构造函数:Person()
age=-858993460,height=-858993460
无参构造函数:Person()
age=-858993460,height=-858993460
无参构造函数:Person()
age=-858993460,height=-858993460
反汇编为
22: //栈空间
23: Person person;
00AF26A2 lea ecx,[person]
00AF26A5 call Person::Person (0AF13F2h)
24:
25: Person person2;
00AF26AA lea ecx,[person2]
00AF26AD call Person::Person (0AF13F2h)
26:
27: Person person3;
00AF26B2 lea ecx,[person3]
00AF26B5 call Person::Person (0AF13F2h)
倘若
Person() {
m_age = 0;
m_height = 0;
cout << "无参构造函数:Person()" << endl;
cout << "age=" << m_age << ",height=" << m_height << endl;
}
则out为
无参构造函数:Person()
age=0,height=0
无参构造函数:Person()
age=0,height=0
无参构造函数:Person()
age=0,height=0
有参的构造函数
#include <iostream>
using namespace std;
class Person {
private:
int m_age;
int m_height;
public:
Person() {
m_age = 0;
cout << "无参构造函数:Person()" << endl;
cout << "age=" << m_age << endl;
}
Person(int age) {
m_age = age;
cout << "有参构造函数:Person(int age)" << endl;
cout << "age=" << m_age << endl;
}
void display() {
cout << "age is" << m_age << endl;
}
};
int main()
{
//栈空间
Person person;//调用无参的构造函数
person.display();
Person person2(20);//调用有一个整型参数的构造函数
person2.display();
Person person3(30);
person3.display();
return 0;
}
out为
无参构造函数:Person()
age=0
age is0
有参构造函数:Person(int age)
age=20
age is20
有参构造函数:Person(int age)
age=30
age is30
查看反汇编
31: //栈空间
32: Person person;//调用无参的构造函数
00745812 lea ecx,[ebp-10h]
00745815 call 007413F2
33: person.display();
0074581A lea ecx,[ebp-10h]
0074581D call 00741442
34:
35: Person person2(20);//调用有一个整型参数的构造函数
00745822 push 14h
00745824 lea ecx,[ebp-20h]
00745827 call 0074143D
36: person2.display();
0074582C lea ecx,[ebp-20h]
0074582F call 00741442
37:
38: Person person3(30);
00745834 push 1Eh
00745836 lea ecx,[ebp-30h]
00745839 call 0074143D
39: person3.display();
0074583E lea ecx,[ebp-30h]
00745841 call 00741442
一旦自定义了构造函数,必须用其中一个自定义构造函数来初始化对象。
包含的含义是
①如果没有自定义构造函数,那么
只能写成
②如果Person person2(20)则表示调用有一个整型参数的构造函数
如果Person person2(20,30)则表示调用有两个整型参数的构造函数
全局区、栈空间和通过new申请的堆空间都会调用构造函数
代码
#include <iostream>
using namespace std;
class Person {
private:
int m_age;
int m_height;
public:
Person() {
m_age = 0;
cout << "无参构造函数:Person()" << endl;
cout << "age=" << m_age << endl;
}
};
Person g_person; //全局区
int main()
{
//栈空间
Person person;
//堆空间
Person* p = new Person;
cout << " sizeof(Person) = " << sizeof(Person) << endl; //Person类的size是8
delete p;
return 0;
}
out为
无参构造函数:Person()
age=0
无参构造函数:Person()
age=0
无参构造函数:Person()
age=0
sizeof(Person) = 8
24: //栈空间
25: Person person;
00EA3AAA lea ecx,[person]
00EA3AAD call Person::Person (0EA1483h) //调用构造函数
26: //堆空间
27: Person* p = new Person;
00EA3AB2 push 8
00EA3AB4 call operator new (0EA1140h)
00EA3AB9 add esp,4
00EA3ABC mov dword ptr [ebp-100h],eax
00EA3AC2 mov dword ptr [ebp-4],0
00EA3AC9 cmp dword ptr [ebp-100h],0
00EA3AD0 je main+85h (0EA3AE5h)
00EA3AD2 mov ecx,dword ptr [ebp-100h]
00EA3AD8 call Person::Person (0EA1483h) //调用构造函数
00EA3ADD mov dword ptr [ebp-114h],eax
00EA3AE3 jmp main+8Fh (0EA3AEFh)
00EA3AE5 mov dword ptr [ebp-114h],0
00EA3AEF mov eax,dword ptr [ebp-114h]
00EA3AF5 mov dword ptr [ebp-0F4h],eax
00EA3AFB mov dword ptr [ebp-4],0FFFFFFFFh
00EA3B02 mov ecx,dword ptr [ebp-0F4h]
00EA3B08 mov dword ptr [p],ecx
通过malloc申请堆空间不会调用构造函数
代码如下:
#include <iostream>
using namespace std;
class Person {
public:
int m_age;
Person() {
m_age = 0;
cout << "无参构造函数:Person()" << endl;
cout << "age=" << m_age << endl;
}
void run() {
cout << "Person::run() - " << m_age << endl;
}
};
//全局区
Person g_person;
int main()
{
//栈空间
Person person;
//堆空间
Person* p = new Person;
cout << " sizeof(Person) = " << sizeof(Person) << endl; //Person类的size是8
delete p;
//堆空间
Person* p2 = (Person*)malloc( sizeof(Person) );
p2->m_age = 10;
p2->run();
free(p2);
return 0;
}
out为
无参构造函数:Person()
age=0
无参构造函数:Person()
age=0
无参构造函数:Person()
age=0
sizeof(Person) = 4
Person::run() - 10
malloc初始化的反汇编结果如下,可以看出并未调用构造函数
32: //堆空间
33: Person* p2 = (Person*)malloc( sizeof(Person) );
00403B96 mov esi,esp
00403B98 push 4
00403B9A call dword ptr [__imp__malloc (040E1D8h)]
00403BA0 add esp,4
00403BA3 cmp esi,esp
00403BA5 call __RTC_CheckEsp (04012F8h)
00403BAA mov dword ptr [p2],eax
34: p2->m_age = 10;
00403BAD mov eax,dword ptr [p2]
00403BB0 mov dword ptr [eax],0Ah
35: p2->run();
00403BB6 mov ecx,dword ptr [p2]
00403BB9 call Person::run (04014E7h) //call了run函数
36:
37: free(p2);
00403BBE mov esi,esp
00403BC0 mov eax,dword ptr [p2]
00403BC3 push eax
00403BC4 call dword ptr [__imp__free (040E21Ch)]
00403BCA add esp,4
00403BCD cmp esi,esp
00403BCF call __RTC_CheckEsp (04012F8h)
如果没写构造函数
如果没写构造函数,编译器并不会为类生成空的无参的构造函数
在某些特定的情况下除外,查看以下代码
#include <iostream>
using namespace std;
struct Person {
int m_age = 0; //初始化;若没有初始化,就不会生成空的无参的构造函数
};
int main()
{
//栈空间
Person person;
person.m_age = 10;
return 0;
}
查看反汇编,可以看到调用了构造函数
13: //栈空间
14: Person person;
008D2D02 lea ecx,[person]
008D2D05 call std::operator<<<std::char_traits<char> > (08D14ECh)
15: person.m_age = 10;
008D2D0A mov dword ptr [person],0Ah
008D14EC jmp Person::Person (08D2C90h) //调用构造函数
008D2C90 push ebp
008D2C91 mov ebp,esp
008D2C93 sub esp,0CCh
008D2C99 push ebx
008D2C9A push esi
008D2C9B push edi
008D2C9C push ecx
008D2C9D lea edi,[ebp-0CCh]
008D2CA3 mov ecx,33h
008D2CA8 mov eax,0CCCCCCCCh
008D2CAD rep stos dword ptr es:[edi]
008D2CAF pop ecx
008D2CB0 mov dword ptr [this],ecx
008D2CB3 mov eax,dword ptr [this]
008D2CB6 mov dword ptr [eax],0 // m_age = 0
008D2CBC mov eax,dword ptr [this]
008D2CBF pop edi
008D2CC0 pop esi
008D2CC1 pop ebx
008D2CC2 mov esp,ebp
008D2CC4 pop ebp
008D2CC5 ret
注意事项和总结
1、class默认是private,struct默认是public,所以当需要在main函数中访问类中的成员变量时需要对成员变量的访问权限进行指明(即public)