(3)C++构造函数及初始化和赋值的区别


函数成员


一、构造函数

回顾上节利用函数成员来调用其他成员:
构造函数的产生:

#include
using namespace std;

class Cstu
{
public:
	int age ;//整形数据成员;
	char strong;
	float Heigh ;
	void message() //特别申请一个函数给其他成员初始化  用的时候直接用就好了
	{
		age = 20;
		strong = 'a';
		Heigh = 1.73f;
	}
};
int main()
{
	Cstu we;  //声明一个Cstu类的对象
	we.message();  //调用初始化函数
	cout << we.age << endl;
	system("pause");
	return 0;
} 

构造函数:
1.调用:区别于上者,就是不用调用,系统会自动调用
2.作用:主要是给成员赋值
3.声明方式:

class Cstu
{
public:
	int age ;//整形数据成员;
	char strong;
	float Heigh ;
	Cstu()  //类名 + (参数列表)
	{
		age = 20;
		strong = 'a';
		Heigh = 1.73f;
	}
}

4.注意:
(1)构造函数无返回值
(2)系统在构造函数创建过程中被调用,可以断点查看
(3)系统会给出一个默认的构造函数:

	Cstu()
	{
		//什么也不会执行
	}

届时自定义一个构造函数,默认的就会消失
(4)成员函数可以在类内定义
也可以在类外定义(一定要写作用域,定义时不能写参数值),不过要在类内声明,这种类内声明类外定义的形式多用于多文件,即在头文件声明类,源文件里写函数成员的定义

class Cstu
{
public:
	int age;
	char strong;
	float Heigh;
	Cstu(int a, char b, float c = 1.73f);
	int fun();  //函数声明也叫函数原型
};
Cstu::Cstu(int a, char b, float c) //定义时不能写参数值
{
	int age = a;  //通过参数,给成员赋值
	char strong = b;
	float Heigh = c;
}
int Cstu::fun()   //在函数名字前加类型作用域
{
	return age;
}

5.调用:
(1)栈区对象
(2)堆区对象(指针对象):
a.声明指针并不会调用构造函数

Cstu *we1;  //不会调用 此时并未申请空间接指针
cout << we1->age << endl;

b.只有在new出空间时才会创建

Cstu *we1 = new Cstu; 
cout << we1->age << endl;
delete we1;

6.带参数的构造函数
要点:通过对象传递 可以指定默认值
(1)形式:

	Cstu(int a ,char b , float c)
	{
		age = a;  //通过参数,给成员赋值
		strong = b;
		Heigh = c;
	}

(2)调用:
a.若函数有参数,在创建对象时就一定要把参数传递进来,若不传会报“没有合适的默认构造函数可用”的错误
b.传参

	Cstu we(20, 'w', 1.73f);
	cout << we.age << ' ' << we.Heigh << ' ' << we.strong << endl;

c.函参指定默认值

	Cstu(int a ,char b , float c = 1.73f)
	{
		age = a;  //通过参数,给成员赋值
		strong = b;
		Heigh = c;
	}
	/*传的时候就少一个*/
	Cstu we(20, 'w');

注意:
若默认有,传的时候也有,则传的参数会覆盖默认的值
d.指针对象的传参

Cstu *we1 = new Cstu(21,'q',1.24f);
cout << we1->age << ' ' << we1->Heigh << ' ' << we1->strong << endl;

7.构造函数的重载:与函数重载相同

初始化与赋值区别:

意义上:初始化是一个变量或对象产生之时就赋予一个初始值,伴随性质,比如:int a = 12;那么a产生之时就自带一个值12;赋值是一个变量或对象产生之后的任意时刻可赋予一个值,随意性质

	//引用的初始化与赋值
	int a = 12; //必须初始化
	int &b = a;

	//const:限定的变量无法更改
	const int c = 13;  //必须初始化,不能赋值

函数声明:int fun();
函数定义:

int fun()
{
	int a = 12;
	return a;
}

初始化列表:
1.作用:给数据成员进行初始化
与构造函数区别:构造函数是赋值

class Cstu
{
public:
	int a;
	float f;
	Cstu() //赋值  构造函数一般是赋值,不打印
	{
		a = 13;
	}
	void print()
	{
		cout << a << ' ' << f << endl;
	}

};
//在主函数中调用
Cstu stu;
stu.print();

2.形式:Cstu() :a(12) , f(12.12f) //初始化 构造函数后加
赋值会覆盖初始化列表
3.总结对数据成员的初始化
a.通过数值
b.通过构造函数参数

//构造函数  初始化顺序与声明顺序有关
	int a;
	float f;
    Cstu(int c,float d) :a(c) , f(d) //初始化
	{
		
	}
	void print()
	{
		cout << a << ' ' << f << endl;
	}
	//主函数传递
	Cstu stu (12,12.12f); //调用  传参赋值
	stu.print();

c.通过成员之间互相初始化,注意顺序
如上,a可以初始化f,f可以初始化a

//先初始化a,后初始化f;即先a(f),此时f未知,所以a打印出的是未知数
class Cstu
{
public:
	int a;
	int f;
	Cstu() :f(12), a(f)//先初始化a,后初始化f;即先a(f),此时f未知,所以a打印出的是地址
	//Cstu():a(12),f(a)  此时就对了,a,f都打印12
	{

	}
	void print()
	{
		cout << a << ' ' << f << endl;
	}
};

4.引用和const的初始化
引用:(1)引用成员初始化:
a.直接定义整形a

class Cstu
{
public:
	int b;
	int &a;  //引用整型变量
	Cstu() : a(b) , b(12) //把b赋给a
	{

	}
	void print()
	{
		cout << a << ' ' << b << endl;
	}
};

(2)引用参数初始化
利用传参

class Cstu
{
public:
	int b;
	int &a;  //引用整型变量
	Cstu(int c) : a(b) , b(c) //把b赋给a
	{

	}
	void print()
	{
		cout << a << ' ' << b << endl;
	}
};
//主函数调用
	Cstu we(12);
	we.print();

Cstu(int c) : a(c) , b(c)结果会出错,原因是c为局部变量,此函数结束,c就会不属于它了,值不确定。若在构造函数内输出:如下

	Cstu(int c) : a(c) , b(c) //把b赋给a
	{
		cout << a << ' ' << b << endl;
	}

就会发现值是正常的了
(3)引用类外int d = 12; Cstu we(d);

Cstu(int &c) : a(c) , b(c)   //把d和c指向同一个就好了

引用:

const int e;
	Cstu(int &c) : a(c) , b(c) ,e(c) //原因是,c此时不是变量,而是常量
	{
		cout << a << ' ' << b << endl;
	}
	void print()
	{
		cout << a << ' ' << b << ' ' << e << endl;
	}  //输出e = 14;

5.数组和结构体使用初始化列表

class Cstu
{
public:
	int a[4];
	Cstu() : a()  //这种情况一些编译器不适用
	{
		for (int i = 0; i < 4; i++)
		{
			cout << a[i] << ' ';
		}
	}

};

所以就可以利用循环来初始化

class Cstu
{
public:
	int a[4];
	Cstu()
	{
		for (int i = 0; i < 4; i++)
		{
			a[i] = 0;
		}
	}
	void print()
	{
		for (int i = 0; i < 4; i++)
		{	 
			cout << a[i] << ' ' ;
		}
	}

};

这样初始化显然太麻烦,所以C++就提供了简便的方法
memset //设置连续空间的值 使用方法:memset(首地址,要设置成的值,多少字节)

//如上
memset(&a[0],0,4*4)  //不能越界

结构体的初始化:
1.结构体可以进行相互赋值

struct STU
{
	int i;
	float j;
};
//主函数调用
	STU u1 = { 12, 12.12f };
	STU u2 = u1;
	cout << u2.i << ' ' << u2.j;

实列:

struct westrong//声明一个结构体
{
	int a;
	float b;
};
class stu
{
public:
	westrong we;  //声明成员 we
	stu(westrong wq) : we(wq)   //结构体之间可以进行相互赋值 wq是局部变量也没有值,要通过外部传值
	{
	}
	void print()
	{
		cout << we.a << ' ' << we.b;
	}
};
//主函数调用
	westrong wr = { 12, 12.23f };
	stu tu(wr);
	tu.print();

你可能感兴趣的:(C++基础学习,c++,类,编程语言)