c++类和对象第二部分

运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其 返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号。

函数原型:返回值类型 operator操作符(参数列表)

赋值运算符重载

要注意,赋值运算符只能定义在类中.赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现 一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值
运算符重载只能是类的成员函数

class Date
{
public:
	Date(int hour = 00, int min = 00, int se = 0)
	{
		_hour = hour;
		_min = min;
		_second = se;
	}
	void operator=(const Date& d)
	{
		cout << "void operator=(const Date& d)" << endl;
		_hour = d._hour;
		_min = d._min;
		_second = d._second;
	}
private:
	int _hour;
	int _min;
	int _second;
};

int main()
{
	Date d1(22, 55, 21);
	Date d2 = d1;	// ok
	Date d3;
	d3 = d2 = d1;	//err
	return 0;
}
// 要去除erro,只要将赋值运算符重载改为
Date& operator=(const Date& d)
{
    cout << "Date& operator=(const Date& d)" << endl;
    _hour = d._hour;
    _min = d._min;
    _second = d._second;
    return *this;
}
//可以加上if(*this != &d),防止自己给自己赋值(d2 = d2),这样没有意义,写上这句能增快速度

.* :: sizeof ?:(三目) . 注意以上5个运算符不能重载。

const 修饰符

class Date
{
public:
    Date(int year = 2023, int month = 9, int day = 26)
	{
        //cout << "Date(int year, int month, int day)" << endl;
        _year = year;
        _month = month;
        _day = day;
	}
    void PrintDate()	// 参数为Date* const this
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
private:
	int year;
	int _month;
	int _day;
};
// const 测试
void Test07()
{
	Date d1(2023, 9, 30);
	const Date d2(2023, 8, 30);
	d1.PrintDate();
	d2.PrintDate();
}

上面的代码会报错
因为 d1的类型是 Date* (ok)
d2的类型是 const Date*
把const Date* 传给Date*,出现权限的放大,所以会报错(err)

想要解决,只需要把在函数后面加上const

void PrintDate() const	// 参数为const Date* const this
{
	cout << _year << " " << _month << " " << _day << endl;
}

权限可以缩小,但是不能放大

初始化列表

  1. 每个成员变量在初始化列表只能出现一次,(即只初始化一次)
  2. 以下的成员必须使用初始化列表
    没有默认构造函数的自定义类型的成员
    引用成员变量
    自定义类型成员变量
class A
{
public:
	A(int a)
	{
		_a = a;
	}
private:
	int _a;
};

class B
{
public:
	B(int a, int b, int c) : _a(a), _b(b), _c(c)
	{}
private:
	A _a;	// 没有默认构造函数的自定义类型的成员
	int& _b;	// 引用成员变量
	const int _c;	// 自定义类型成员变量
};
  1. 成员变量在类中声明的顺序就是初始化列表初始化的顺序,与其在列表的先后顺序无关

    // 下面程序的运行结果是?
    class A 
    {
    public:
    	A(int a) :_a1(a), _a2(_a1)	// 在初始化列表过程中可以认为是成员变量的定义
    	{}
    	void Print()
    	{
    		cout << _a1 << " " << _a2 << endl;
    	}
    private:
    	// 成员变量的生命
    	int _a2;
    	int _a1;
    };
    

    运行结果是 1 随机值

explicit关键字

对于单个参数或者 除第一个参数无默认值其余均有默认值的构造函数

class Date
{
public:
	Date(int year) : _year(year)
	{
		cout << "Date(int year)" << endl;
	}
	Date(const Date& d)
	{
		_year = d._year;
		cout << "Date(const Date& d)" << endl;
	}
private:
	int _year;
};

int main() 
{
	Date d1(2023);	// 直接调用构造
	Date d2 = 2023;	// 构造+拷贝构造: 编译器优化为->直接调用构造

	const Date& d2 = 2023;	// 先用2023构造了一个临时变量,临时变量具有常性,所以要加const
	return 0;
}
/*
运行结果:
Date(int year)
Date(int year)
Date(int year)

*/

如果不想让20行编译器进行优化,可以将在构造函数前加上explicit,禁止这种隐式类型转换

此时,上面的20行,22行均会报错,禁止这种隐式转换

匿名对象

没有名字的对象,声明周期只有这一行

int main() 
{
	Date(2000);
	return 0;
}
// 通过调试可以发现,到第3行结束时,已经调用完了Date类的构造函数和析构函数

静态成员

概念

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用 static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化

特点

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. . 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制
class A
{
public:
	A()	{_scount++;}
	// 静态成员函数,没有this指针
	static int GetCount()		
	{
		//cout << _a << endl;  // err
		return _scount;
	}
private:
	int _a;
	// 静态成员变量,属于整个类,声明周期在整个程序运行期间,储存在静态区
	static int _scount;		// 声明
};

int A::_scount = 0;		// 在类外定义初始化

int main()
{
	A a;
	A a1;
	A a2;
	
	//cout << A::_scount << endl;
	//cout << a._scount << endl;
	//cout << a2._scount << endl;
	
	cout << a.GetCount() << endl;

	return 0;
}

静态成员函数,不能调用非静态成员函数,因为没有this指针
非静态成员函数可以调用类的静态成员函数

设计一个只能在栈上定义对象的类

class StackOnly
{
public:
	static StackOnly CreatObj()		// 提供一个静态成员函数供外界使用
	{
		StackOnly s;
		return s;
	}
private:
	int _a;
	StackOnly(int a = 0) : _a(a){}		// 将构造函数私有化
};

int main()
{
	StackOnly s = StackOnly::CreatObj();
	StackOnly s2 = StackOnly::CreatObj();
	return 0;
}
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值