C++ 类与对象(2)

一.类的六个默认函数
构造函数:构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有 一个合适的初始值,并且在对象的生命周期内只调用一次。
构造函数的特性:构造函数是特殊的成员函数,需要注意的是,构造函数的虽然名称叫构造,但是需要注意的是构造函数的主要任务并不是开空间创建对象,而是初始化对象。如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。

  1.函数名与类名相同。
  2.无返回值。
  3.对象实例化时编译器自动调用对应的构造函数。
  4.构造函数可以重载。

析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成类的资源清理工作。
析构函数的特性:析构函数是特殊的成员函数。

 1.析构函数名是在类名前加上字符 ~。
 2.无参数无返回值。
 3.一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
 4.对象生命周期结束时,C++编译系统系统自动调用析构函数

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
**拷贝构造函数特性:**拷贝构造函数也是特殊的成员函数

1. 拷贝构造函数是构造函数的一个重载形式。
2. 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
3. 若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝。

深拷贝:

class String
{
public:
	String(const char* string = "")
	{
		int len = strlen(string) + 1;
		m_data = (char*)malloc(strlen(string) + 1);
		strcpy(m_data, string);
	}
	String(const String& s)  //深拷贝
	{
		m_data = (char*)malloc(strlen(s.m_data) + 1);
		strcpy(m_data, s.m_data);
	}
	//申请空间之前  把当前空间所管的释放掉
	//这个也属于异常不安全的代码
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			free(m_data);  //释放当前所管的空间
			m_data = (char*)malloc(strlen(s.m_data) + 1);
			strcpy(m_data, s.m_data);
		}
		return *this;
	}
	~String()
	{
		free(m_data);
		m_data = nullptr;
	}
public :
	void Show()const
	{
		cout << m_data << endl;
	}
private:
	char* m_data;  //如果类是指针成员  一定要用深拷贝和深赋值  函数都要重写
};

void main()
{
	char str[] = "abcxyz";
	cout << strlen(str) << endl;
	cout << sizeof(str) << endl;

	String s("abcef");
	s.Show();
	String s1 = s;
	String s2;
	s2 = s1;   //相当于 s2 operator=(s1)
}

赋值运算符重载:C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接重载运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
注意

1.不能通过连接其他符号来创建新的操作符:比如operator@ 
2.重载操作符必须有一个类类型或者枚举类型的操作数 
3..* 、:: 、sizeof 、?: 、. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。
class Complex
{
	
public:
	Complex(int real=0,int imag=0):m_real(real),m_imag(imag)
	{}
	~Complex()
	{}
public:
	friend Complex operator+(int value, const Complex& x);  //友元必须真真实实给出参数
	friend ostream& operator<<(ostream& out, const Complex& x);
public:
	Complex operator+(const Complex& c)
	{
		return Complex(m_real + c.m_real, m_imag + c.m_imag);
	}
	Complex operator-(const Complex& c)
	{
		return Complex(m_real - c.m_real, m_imag + c.m_imag);
	}
public:
	Complex operator+(int value)
	{
		return Complex(m_real + value, m_imag );
	}
private:
	int m_real;
	int m_imag;
};
Complex operator+(int value, const Complex& x)
{
	return Complex(value + x.m_real, x.m_imag);
}
ostream& operator<<(ostream& out, const Complex& x)
{
	out << "(" << x.m_real << "," << x.m_imag << ")";
	return out;
}
void main()
{
	Complex c1(1, 2);
	Complex c2(3, 4);
	Complex x = c1 + c2;
	Complex y = c1 + 10;

	cout << c1 << endl;
}

const成员:将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

class test
{
public:
	//构造函数
	test(int data = 0)
	{
		m_data = data;
	}
	//拷贝函数
	test(const test& t)
	{
		m_data = t.m_data;
	}
	//赋值
	test& operator=(const test& t)
	{
		if (this != &t)
		{
			m_data = t.m_data;
		}
		return *this;
	}
	//析构函数
	~test()
	{}
```public:
	void SetData(int data)
	{
		m_data = data;
	}
	//int GetData(const Test * const this)  加了const就变成了常量  不允许修改
	int GetData() const // 常方法
	{
		return m_data;
	}
	//int GetData(Test *const this)   这两种方法是可以同时存在的  发生了重载
	int GetData()
	{
		return m_data;
	}
private:
	int m_data;
};

void main()
{
	Test t;  //常方法普通对象是可以调用的  常对象只能调用常方法
	cout << "t=" << t.GetData() << endl;
	t.SetData(100);
	cout << "t=" << t.GetData() << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值