4、c++的运算符

运算符

作用:用于执行代码的运算

运算符类型 作用
算术运算符 用于处理四则运算
赋值运算符 用于将表达式的值赋给变量
比较运算符 用于表达式的比较,并返回一个真值或假值
逻辑运算符 用于根据表达式的值返回真值或假值

算术运算符

作用:用于处理四则运算

和java的基本相同

运算符 术语 示例 结果
+ 正号 +3 3
- 负号 -3 -3
+ 10 + 5 15
- 10 - 5 5
* 10 * 5 50
/ 10 / 5 2
% 取模(取余) 10 % 3 1
++ 前置递增 a=2; b=++a; a=3; b=3;
++ 后置递增 a=2; b=a++; a=3; b=2;
-- 前置递减 a=2; b=--a; a=1; b=1;
-- 后置递减 a=2; b=a--; a=1; b=2;

字符串拼接

如果需要字符串拼接int等数值类型的话,那么不可以和java一样,直接使用+去加,而是需要使用基本命名空间std中的to_string()函数

#include<iostream>
#include<string>

using namespace std;

int main() {
	int a = 10;
	double b = 25.4;
	bool c = true;

	string str = "你好呀";

	string joint1 = str + to_string(a);
	string joint2 = str + to_string(b);
	string joint3 = str + to_string(c);

	cout << joint1 << endl;
	cout << joint2 << endl;
	cout << joint3 << endl;

	system("pause");
	return 0;
}

赋值运算符

作用:用于将表达式的值赋给变量

和java基本相同

运算符 术语 示例 结果
= 赋值 a=2; b=3; a=2; b=3;
+= 加等于 a=0; a+=2; a=2;
-= 减等于 a=5; a-=3; a=2;
*= 乘等于 a=2; a*=2; a=4;
/= 除等于 a=4; a/=2; a=2;
%= 模等于 a=3; a%2; a=1;

比较运算符

作用:用于表达式的比较,并返回一个真值或假值,也就是bool类型

运算符 术语 示例 结果
== 相等于 4 == 3 0
!= 不等于 4 != 3 1
< 小于 4 < 3 0
> 大于 4 > 3 1
<= 小于等于 4 <= 3 0
>= 大于等于 4 >= 1 1

逻辑运算符

作用:用于根据表达式的值返回真值或假值

和java的用法相同,与和或都是短路的

运算符 术语 示例 结果
! !a 如果a为假,则!a为真; 如果a为真,则!a为假。
&& a && b 如果a和b都为真,则结果为真,否则为假。
|| a || b 如果a和b有一个为真,则结果为真,二者都为假时,结果为假。

例子:

#include<iostream>
using namespace std;

int main() {

	int i = 1;
	
	bool a = 10 > 1 || i++;

	cout << a << endl; //1
	cout << i << endl; //1
	
	
	system("pause");
	return 0;
}

运算符重载

运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

作用:实现两个自定义数据类型的运算

语法:只需要在需要自定义运算逻辑的类中,声明函数,然后把函数的名字换为operator运算符即可

加号运算符

#include<iostream>

using namespace std;

class Person {
private:
	int age;
public:
    //构造函数,设置age
	Person(int age) {
		this->age = age;
	}
    //运算符+重载,返回一个新的Person对象,age为二者age之和
	Person operator+(Person & person) {
		int totalAge = this->age + person.age;
		Person p(totalAge);
		return p;
	}
	int getAge() {
		return this->age;
	}
};

int main() {
	Person p1(18);
	Person p2(20);
    //使用的时候,就可以直接使用+运算符,而不需要调用函数
	Person p3 = p1 + p2;
	cout << p3.getAge() << endl;
    return 0;
}

左移运算符

由于之前的输出语句是cout << "msg";,cout是ostream类型的对象,那么,我们可以重载在一运算符,实现输出自定义类型对象

#include<iostream>
#include<string>

using namespace std;

class Person {
	//将全局函数声明为友元,可以访问私有属性
	friend ostream& operator<<(ostream & out, Person& p);
private:
	int age;
	string name;
public:
	Person(int age,string name) {
		this->age = age;
		this->name = name;
	}
	//如果作为成员函数出现,那么实质上就是,person.operator<<(person),这么不符合逻辑
	//所以,为了可以达到ostream operator<<(Person person,ostream c)的效果,我们需要把这个声明为全局函数
	//ostream&  operator<<(Person & person);
};

//全局函数,重载左移运算符
ostream& operator<<(ostream & out,Person& p) {
	string msg = "姓名:" + p.name + ",年龄:" + std::to_string(p.age);
	out << msg;
	return out;
}

int main() {
	Person p(18, "Lucy");

	cout << p << endl; //姓名:Lucy,年龄:18

	return 0;
}

递增运算符重载


class MyInteger {

	friend ostream& operator<<(ostream& out, MyInteger myint);

public:
	MyInteger() {
		m_Num = 0;
	}
	//前置++
	MyInteger& operator++() {
		//先++
		m_Num++;
		//再返回
		return *this;
	}

	//后置++
	MyInteger operator++(int) {
		//先返回
		MyInteger temp = *this; //记录当前本身的值,然后让本身的值加1,但是返回的是以前的值,达到先返回后++;
		m_Num++;
		return temp;
	}

private:
	int m_Num;
};


ostream& operator<<(ostream& out, MyInteger myint) {
	out << myint.m_Num;
	return out;
}


//前置++ 先++ 再返回
void test01() {
	MyInteger myInt;
	cout << ++myInt << endl;
	cout << myInt << endl;
}

//后置++ 先返回 再++
void test02() {

	MyInteger myInt;
	cout << myInt++ << endl;
	cout << myInt << endl;
}

int main() {

	test01();
	//test02();

	system("pause");

	return 0;
}

赋值运算符重载

c++编译器至少给一个类添加4个函数

  1. 默认构造函数(无参,函数体为空)
  2. 默认析构函数(无参,函数体为空)
  3. 默认拷贝构造函数,对属性进行值拷贝
  4. 赋值运算符 operator=, 对属性进行值拷贝

如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

class Person
{
public:

	Person(int age)
	{
		//将年龄数据开辟到堆区
		m_Age = new int(age);
	}

	//重载赋值运算符 
	Person& operator=(Person &p)
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
		//编译器提供的代码是浅拷贝
		//m_Age = p.m_Age;

		//提供深拷贝 解决浅拷贝的问题
		m_Age = new int(*p.m_Age);

		//返回自身
		return *this;
	}


	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}

	//年龄的指针
	int *m_Age;

};


void test01()
{
	Person p1(18);

	Person p2(20);

	Person p3(30);

	p3 = p2 = p1; //赋值操作

	cout << "p1的年龄为:" << *p1.m_Age << endl;

	cout << "p2的年龄为:" << *p2.m_Age << endl;

	cout << "p3的年龄为:" << *p3.m_Age << endl;
}

int main() {

	test01();

	//int a = 10;
	//int b = 20;
	//int c = 30;

	//c = b = a;
	//cout << "a = " << a << endl;
	//cout << "b = " << b << endl;
	//cout << "c = " << c << endl;

	system("pause");

	return 0;
}

关系运算符重载

class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	};

	bool operator==(Person & p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	bool operator!=(Person & p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	string m_Name;
	int m_Age;
};

void test01()
{
	//int a = 0;
	//int b = 0;

	Person a("孙悟空", 18);
	Person b("孙悟空", 18);

	if (a == b)
	{
		cout << "a和b相等" << endl;
	}
	else
	{
		cout << "a和b不相等" << endl;
	}

	if (a != b)
	{
		cout << "a和b不相等" << endl;
	}
	else
	{
		cout << "a和b相等" << endl;
	}
}


int main() {

	test01();

	system("pause");

	return 0;
}

函数调用运算符重载

class MyPrint
{
public:
	void operator()(string text)
	{
		cout << text << endl;
	}

};
void test01()
{
	//重载的()操作符 也称为仿函数
	MyPrint myFunc;
	myFunc("hello world");
}


class MyAdd
{
public:
	int operator()(int v1, int v2)
	{
		return v1 + v2;
	}
};

void test02()
{
	MyAdd add;
	int ret = add(10, 10);
	cout << "ret = " << ret << endl;

	//匿名对象调用  
	cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
}

int main() {

	test01();
	test02();

	system("pause");

	return 0;
}