C++学习之路—面向对象—构造函数

定义

构造函数也叫构造器,在对象创建的时候自动调用,一般用于完成对象的初始化工作

下方示例中Person()就是类的构造函数

class Person
{
public:
	Person();//创建类时自动创建的构造函数,也可以手动添加,这个为构造函数的声明
	~Person();//虚构函数,后续文章会记录

	int m_member;

private:

};

Person::Person()//构造函数的实现-无参数构造函数
{
	cout << "创建了对象,构造函数自动执行" << endl;
	//构造函数里可以做一下成员变量的初始化工作,因为对象创建成功,构造函数就直接调用,比如:
	m_member = 5;
}

int main()
{
	Person person1;//创建了这个对象的时候,构造函数就直接自动调用了
	cout << person1.m_member << endl;//打印为5

	getchar();
	return 0;
}

构造函数的用途

就记住一个最大的用途,就是初始化类中的成员变量(这与python中的def _ init _()函数一样)

使用构造函数有几点需要注意

  • 新建类的时候,像VS这种IDE会给你自动添加构造函数,包括类中的构造函数声明,实现中的构造函数实现。
  • 构造函数名与类同名无返回值(void都不可以写),可以有参数可以重载可以有多个构造函数
  • 一旦自定义了构造函数,必须用自定义的构造函数来创建初始化对象。这也就意味着如果类中有自己写的构造函数,然后你没有与之对应的对象示例化,就会报错
class Person
{
public:
	Person(int a,int b);//创建类时自动创建的构造函数,也可以手动添加,这个为构造函数的声明
	int m_member;
	int m_value;

private:

};
Person::Person(int a,int b)//构造函数的实现-有参数构造函数
{
	m_member = a;
	m_value = b;
}

int main()
{
	Person person1;//只这么创建对象,会报错,因为和仅仅独存的构造函数对应不上
	Person person2(10,20);//必须这么创建对象,得和构造函数对应上

	getchar();
	return 0;
}
  • 但如果有多个构造函数,就可以实现构造函数的重载
class Person
{
public:
	Person(int a,int b);//创建类时自动创建的构造函数,也可以手动添加,这个为构造函数的声明
	Person();
	int m_member;
	int m_value;

private:

};
Person::Person(int a,int b)//构造函数的实现-有参数构造函数
{
	m_member = a;
	m_value = b;
}

Person::Person()//构造函数的实现-有参数构造函数
{
	m_member = 0;
	m_value = 0;
}

int main()
{
	Person person1;//只这么创建对象,就不会报错,因为有与之对应的构造函数
	Person person2(10,20);//必须这么创建对象,得和构造函数对应上

	getchar();
	return 0;
}
  • 如果类中没写构造函数,必须采用Person person这样的方式创建对象,不可以Person person(10)这种创建对象
class Person
{
public:
	int m_member;
	int m_value;

private:

};
int main()
{
	Person person1;//由于类中没有声明构造函数,所以必须这么创建对象
	Person person2(10);//没有与之对应的构造函数,这样创建对象是错的

	getchar();
	return 0;
}
  • 通过malloc创建的对象不会调用构造函数,但通过new创建的对象会调用构造函数。同样是堆空间开辟内存,但是调用构造函数与否却有差别。
    new对比malloc,同样都是申请堆空间内存,但是比malloc多做了一个事情就是调用构造函数
class Person
{
public:
	int m_member;
	int m_value;

private:

};
int main()
{
	Person *p_malloc = (Person *)malloc(sizeof(Person));//不会调用构造函数
	free(p_malloc);//防止内存泄漏

	Person *p_new = new Person;//会调用构造函数
	delete p_new;//防止内存泄漏
}

malloc只申请堆空间,不可以调用构造函数,即,不可以直接初始化成员变量,想要初始化就必须调用memset函数
new既可以申请堆空间,又可以调用构造函数达到初始化成员变量的目的,还可以直接初始化成员变量:Person *p = new Person(0)
*
C++中想要把对象放在堆空间,尽量用new,别用malloc,因为new才会调用构造函数,才会初始化一些成员变量。

调用构造函数的不同情况

下面三种创建对象的方法,都会调用哪个构造函数呢?

class Person
{
public:
	Person();//创建类时自动创建的构造函数,也可以手动添加,这个为构造函数的声明
	Person(int value);//与默认的构造函数形成重载
private:

};

Person::Person()//构造函数的实现-无参数构造函数
{
	cout << "无参构造函数的调用" << endl;
}

Person::Person(int value)//构造函数的实现-有参数构造函数
{
	cout << "有参构造函数的调用" << endl;
}

int main()
{
	
	//这三个会自动调用哪个构造函数呢?
	Person f_person0;//会调用无参的Person::Person()
	Person f_person1();//这其实是个函数声明,只不过返回值是Person类型的
	Person f_person2(10);//会调用有参的Person::Person(int parm)

	//这三个会自动调用哪个构造函数呢?
	Person *p0 = new Person;//会调用无参的Person::Person()
	Person *p1 = new Person();//会调用无参的Person::Person(),如果是new int()代表这四个字节初始化为0,但是new 类 不是这样的
	Person *p2 = new Person(10);//会调用有参的Person::Person(int value),//注意这样里面写成10,不代表将Person下的成员变量全部初始化为10,
                                                                     //因为这个10其实是实参,但如果没有定义构造函数,这个10就是默认全部初始化为10了
	getchar();
	return 0;
}

括号里没有参数:new int()和new Class()是不一样的。

new int()代表的是初始化内存空间都为0
new Person()表示的是会调用无参的构造函数

括号里有参数:new int(10)和new Person(10)是不一样的。

new int(10)代表的是初始化内存空间都为10,这个10是放在这块内存的数值
new Person(10)表示的是会调用有参的构造函数,这个10是实参

关于构造函数的一个广为流传的错误:

错误原话:默认情况下,编译器会为每一个类生成空的、无参的构造函数,即Person(); 这句话在C++里是错的,不严谨。
严谨表达:如果你在类中定义成员变量时,对成员变量进行赋值操作了,那么编译器就会为你默认生成空的、无参的构造函数,即Person()。反过来,如果没有对变量进行初始化操作,就不会生成空的、无参构造函数。

class Person
{
public:
	int m_member;//如果类中这么定义变量,创建对象时,编译器就不会为这个类创建空的无参的构造函数
	int m_member=0;//如果类中这么定义变量,创建对象时,编译器就会为这个类创建空的无参的构造函数
private:
};

成员变量初始化问题

无自定义构造函数情况下,成员变量初始化问题

即我不写构造函数,然后分别在全局区、栈空间、堆空间创建对象,看看哪个内存区间的对象默认初始化成员变量

class Person
{
public:
	int m_age;
private:
	int m_height;
};

//全局区,
Person g_person; //初始化了成员变量为0

int main()
{
	//栈空间
	Person person;//没有初始化

	//堆空间
	Person *p0 = new Person;//没有初始化
	Person *p1 = new Person();//初始化了成员变量为0,

	cout << g_person.m_age << endl;//0,说明初始化了成员变量为0
	cout << person.m_age << endl;//报错 “使用了未初始化的局部变量“person” 说明没有初始化成员变量
	cout << p0->m_age << endl;//-85818896185,说明没有初始化成员变量,随机赋值了
	cout << p1->m_age << endl;//0,说明初始化了成员变量为0

	getchar();
	return 0;
}
  • 初始化在全局区的对象,会默认初始化成员变量为0
  • 初始化在栈空间的对象,不会初始化成员变量
  • 初始化在堆空间的对象,类名后加括号的会默认初始化成员变量为0,不加括号的不会初始化成员变量

定义构造函数情况下,但构造函数里无实现,此时成员变量初始化问题

如果我声明了构造函数,但是没有实现,即,函数没有函数体,Person *p1 = new Person();这样就不会初始化成员变量了,因为它自动调用了没有实现的构造函数

class Person
{
public:
	int m_age;
	Person(){
	//无实现
	}
private:
	int m_height;
};

int main()
{

	//堆空间
	Person *p0 = new Person;//没有初始化
	Person *p1 = new Person();//这样也没有初始化

	cout << p0->m_age << endl;//-85818896185,说明没有初始化成员变量,随机赋值了
	cout << p1->m_age << endl;//-85818896185,说明没有初始化成员变量,随机赋值了

	getchar();
	return 0;
}

总结初始化成员变量的问题

所以,总结一下初始化变量的问题

  • 如果没有定义构造函数,栈空间和堆空间的一种情况是不会初始化成员变量的,就是Person不带括号的情况;
  • 全局区定义的变量,都默认初始化为0,无论是对象、变量…
  • 如果自定义了构造函数,除了全局区,其他内存空间的成员变量默认都不会初始化,除非你手动在构造函数里初始化
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值