C++ 1.2 this指针 构造函数

一、this 指针(节省空间,时间换空间)

对象可以根据属性来区分,为了降低空间复杂度,可以让同类型对象共享一份成员函数。

1.编译器针对设计的类型分三步编译:

(1)识别和记录类中的属性(名称、类型、访问限定)

(2)识别和记录类中函数的声明

例如:对于以下代码,调用函数funa()时其内部调用func(),func()在funa()后面定义,故显示无法识别func(),除非先声明 void func(); 才可。

#include
using namespace std;
void funa()
{
	func();
}
void func()
{
}
int main()
{
	funa();//会显示无法编译通过
	return 0;
}

而如果是类成员函数则可以编译通过。正是由于编译器对设计的类分三步编译(主要由于第二步):

#include
using namespace std;
class Fun
{
public:
	void funa()
	//void funa(Fun* const this)
	{
		func();//this->func();
	}
	void func()
	//void func(Fun* const this)
	{
	}
};
int main()
{
	Fun c1;
	c1.funa();//funa(&c1);
	return 0;
}

(3)改写在类中定义函数的参数列表(形参列表加入this指针,类名*const this)和函数体(出现成员变量的地方改为this->属性),改写对象调用成员函数的形式(c1.CountTotal变为CountTotal(&c1))。

下面为C++ 1.1中代码编译的效果(改写在注释中):

#include
using namespace std;
const int LEN{ 20 };
class CGoods
{
private: 
	char Name[LEN];
	int Amount;
	float Price;
	float Total_Price;
public:
	void RegisterGoods(const char*, int, float);
	//void RegisterGoods(CGoods* const this,const char*,int,float);
	void CountTotal();
	//void CountTotal(CGoods* const this);
	const char* Get_name();
	//const char* Get_name(CGoods* const this);
	int Get_amount(); //同理
	float Get_price(); //
	float Get_totalprice() //float Get_totalprice(CGoods* const this)
	{
		return Total_Price;
		//return this->Total_Price;
	}
};
//返回值类型 类名::函数名(参数列表){}
void CGoods::RegisterGoods(const char* name, int amount, float price)
//void CGoods::RegisterGoods(CGoods* const this,const char* name, int amount, float price)
{
	strcpy_s(Name, LEN, name);
	//strcpy_s(this->Name,LEN,name);
	Amount = amount;
	//this->Amount=amount;
	Price = price;
	//this->Price=price;
}
void CGoods::CountTotal()
//void CGoods::CountTotal(CGood* const this)
{
	Total_Price = Price * Amount;
	//this->Total_Price=this->Price * this->Amount;
}
const char* CGoods::Get_name() { return Name; }
int CGoods::Get_amount() { return Amount; }
float CGoods::Get_price() { return Price; }
float CGoods::Get_totalprice() { return Total_Price; }
int main()
{
	CGoods c1;
	c1.RegisterGoods("C++", 15, 29);
	//RegisterGoods(&c1,"C++", 15, 29);
	c1.CountTotal();
	//CountTotal(&c1);
	return 0;
}

 2.仅有类成员函数有this指针(this指针实质为成员函数的一个形参,函数调用时产生this指针,函数调用结束this指针消失),全局函数也无this指针。

二、构造函数

1.数据成员多为私有,要对其进行初始化,必须用一个公有函数来进行,该函数为构造函数(类成员函数,有this指针)

构造函数作用:(1)创建对象;(2)初始化对象属性;(3)进行类型转换

构造函数特征:(1)函数名与类名同;(2)无返回类型(!=void),构造函数返回构造的对象;(3)构造函数在对象生存期内只被调用一次!(4)构造函数可以重载;(5)类中若未定义构造函数,则会自定义一个缺省的(无参、只可构造对象,不可初始化),无参构造函数=各参数均有缺省值=缺省构造函数

#include
using namespace std;
class Complex
{
private:
	int Real;
	int Image;
public:
	Complex()
	//Complex(Complex* const this)
	{
		Real = 0;//若不给值~为随机值
		Image = 0;
	}
	Complex(int x, int y)
	{
		Real = x;
		Image = y;
	}
	void Print()
	{
		cout << "Real:" << Real << "  Image:" << Image << endl;
	}
};
int main()
{
	Complex c1;//调用无参构造函数,构造对象,不初始化
	Complex c2(12, 23);//调用两参构造函数构造对象并初始化
	c1.Print();
	c2.Print();
	return 0;
}

2.空间只能申请。有空间不一定有对象,有对象一定有空间。

#include
using namespace std;
class Empty
{
};
int main()
{
	Empty a1;//由于分配空间,故需要占位符1个字节
	cout << sizeof(a1) << endl;
}

3.虽然说构造函数在对象生存期内只被调用一次,但可以打破规则使用定位new实现2次调用(不要轻易进行二次调用)

Complex c1; //c1调用构造函数初始化c1.Real=0,c1.Image=0

new(&c1) Complex(23,34); //定位new,再次调用构造函数重新对c1的属性初始化

4.缺省构造函数只能有一个!Complex(){} 和Complex(int x=0,int y=0){} 均代表缺省构造函数。

5.如下代码:c2对象无法创建,系统识别为函数的声明。 

#include
using namespace std;
class Complex
{
private:
	int Real;
	int Image;
public:
	Complex()
	{
		Real = 0;//若不给值~为随机值
		Image = 0;
	}
	Complex(int x, int y)
	{
		Real = x;
		Image = y;
	}
};
int main()
{
	Complex c1;
	Complex c2();//c2对象无法创建,由于编译器会识别为函数的声明。
	Complex c3(12, 23);
	Complex c4 = Complex(1, 2);//编译器识别为:Complex c4(1,2);
	c4 = Complex(12, 25);//与上一句不同,先产生一个新对象,再赋值。
	Complex c5{};
	Complex c6{ 2,3 };//优先采用!
	return 0;
}

6.初始化!=赋值。初始化=构建对象时即赋值(效率高!)。

class Complex
{
private:
	int Real;
	int Image;
public:
	Complex():Real{},Image{} //Real(0),Image(0)
	{
		//Real = 0;
		//Image = 0;
	}
	Complex(int x, int y):Real{x},Image{y} //Real(x),Image(y) 初始化
	{
		//Real = x;//赋值
		//Image = y;
	}
};

如下代码:构造函数构建对象的次序是以类中成员属性设计的次序构建的!!与初始化列表次序无关。

#include
using namespace std;
class Complex
{
private:
	int Real;
	int Image;
public:
	Complex(int x):Real{Image},Image{x}
	{
	}
	void Print()
	{
		cout << "Real=" << Real << "  Image=" << Image << endl;
	}
};
int main()
{
	Complex c1{3};
	c1.Print();
	return 0;
}

结果如图,Real先构建,是用随机值构建的:38407cef1cf949c4b89300fe7117f897.png

 

 

你可能感兴趣的:(C++,c++,开发语言)