c++运算符重载

简介: c++运算符重载

运算符重载


加法运算符重载


分别可以通过成员函数,全局函数进行


#include <iostream>
using namespace std;
class Person
{
public:
    //第一种成员函数重载
  Person operator+(Person &p)
  {
  Person temp;
  temp.m_A = this->m_A + p.m_A;
  temp.m_B = this->m_B + p.m_B;
  return temp;
  }
public:
  int m_A;
  int m_B;
};
//第二种全局函数重载
Person operator+(Person &p1,Person &p2)
{
  Person temp;
  temp.m_A = p1.m_A + p2.m_B;
  temp.m_B = p1.m_B + p2.m_B;
  return temp;
}
void test()
{
  Person p1;
  p1.m_A = 10;
  p1.m_B = 10;
  Person p2;
  p2.m_A = 10;
  p2.m_B = 10;
  Person p3;
  //原本成员函数调用方式为:p3 = p1.operator+(p2)  
  //原本全局函数调用方式为:p3 = operator+(p1,p2)
    //都可以简化为p3 = p1 + p2
  p3 = p1+p2;
  cout<<"p3.m_A = "<<p3.m_A<<endl;
  cout<<"p3.m_B = "<<p3.m_B<<endl;
}
int main()
{
  test();
  system("pause");
  return 0;
}



左移运算符重载


不用成员函数:无法实现cout在左侧

可以用全局函数


试一下使用成员函数写出来,发现不行


class Person
{
public:
    void operator<<(ostream &cout) //先定义类再调用,这样的写的话就为p<<cout
    {
      ...
    }
  ...;
}//显然是不行的,那么试一下全局函数


再用全局函数实现


#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
  int m_a;
  int m_b;
};
//采用全局函数进行重载
void operator<<(ostream &cout,Person &p)  //ostream为标准输出流
{
  cout<<"m_a = "<<p.m_a<<" m_b = "<<p.m_b;
  //其中cout也可以改为其他名字
  //例:operator<<(ostream &out,Person &p)
  //然后进行输出 out<<.........
}
void test()
{
  Person p;
  p.m_a = 10;
  p.m_b = 10;
  cout<<p;
}
int main()
{
  test();
  system("pause");
  return 0;
}



再试一下cout<<p<<endl;发现报错了


2 IntelliSense: 无法确定需要哪个 重载函数 "endl" 实例


如果还是返回cout,再接上<<endl就可以解决

解决:让全局函数进行返回


ostream & operator<<(ostream &cout,Person &p)
{
  cout<<"m_a = "<<p.m_a<<" m_b = "<<p.m_b;
  return cout;  //这样返回一个cout就能连上<<endl以及其他输出
}


递增运算符重载


写在成员函数中

分别为前置递增和后置递增


#include <iostream>
#include <string>
using namespace std;
class Myint
{
  friend ostream & operator<<(ostream &cout,Myint &p);
public:
  Myint()
  {
  m_int = 0;
  }
  //前置++运算符
     Myint &operator++()
  {
  m_int++;
  return *this;
  }
  //后置++运算符
  Myint operator++(int)
  {
  Myint temp = *this;
  m_int++;
  return temp;
  }
private:
  int m_int;
};
//左移运算符
ostream & operator<<(ostream &cout,Myint &p)
{
  cout<<p.m_int;
  return cout;
}
//前置++测试
void test01()
{
  Myint mint;
  cout<<++(++mint)<<endl;
  cout<<mint<<endl;   //测试两次++后的结果,若成员函数没有&,返回的是值,那么第二次则是开辟新的对象
}
//后置++测试
void test02()
{
  Myint mint;
  cout<<mint++<<endl;
  cout<<mint<<endl;   //测试完成后置++运算
}
int main()
{
  test02();
  system("pause");
  return 0;
}



赋值运算符重载


#include <iostream>
#include <string>
using namespace std;
class Person 
{
public:
  Person(int age)
  {
  m_age = new int(age);
  }
  int *m_age;   //定义一个指针
};  
void test01()
{
  Person p1(10);
  Person p2(20);
  p1 = p2;   //试着直接运行通过了
  cout<<"p1的年龄为:"<<*p1.m_age<<endl;
  cout<<"p2的年龄为: "<<*p2.m_age<<endl;
}
int main()
{
  test01();
  system("pause");
  return 0;
}



这里进行运行直接通过了,我们再在成员函数中加一个析构函数进行释放内存


~Person() //写一下析构函数,并且释放指针指向内存
  {
  if(m_age != NULL)
  {
    delete m_age;
    m_age = NULL;
  }
  }


再运行一下发现程序直接崩了,原因是原本系统给我们的类中的拷贝构造函数是进行的浅拷贝,到后面进行赋值过后,两个指针同时指向同一个内存

,当第一个指向的内存地址为空,再进行释放,那么就会出现问题


解决办法:自己写一个拷贝构造函数,只不过是内部是进行深拷贝


//写一个赋值 运算符成员函数在类中
  void 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);  //开辟新的内存空间给m_age,也就是深拷贝
  }


此时运行通过


那当我们再创建一个对象


Person p3(30) //在test01中
p3 = p2 = p1  //此时再运行程序


1 IntelliSense: 没有与这些操作数匹配的 "=" 运算符


分析:此时我们应当为自己写的拷贝构造函数增添一个返回值 使p3 等于一个对象,而不是空 (在进行p2 = p1时,函数并没有返回什么,是void类型,那么就会出错)


解决:


//写一个赋值 运算符函数
  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);  //开辟新的内存空间给m_age,也就是深拷贝
  return *this;  //*this返回对象本身
  }


再进行运行程序,就可以通过了


完整赋值运算符重载代码:


#include <iostream>
#include <string>
using namespace std;
class Person 
{
public:
  Person(int age)
  {
  m_age = new int(age);
  }
  ~Person() //写一下析构函数,并且释放指针指向内存
  {
  if(m_age != NULL)
  {
    delete m_age;
    m_age = NULL;
  }
  }
  //写一个赋值 运算符函数
  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);  //开辟新的内存空间给m_age,也就是深拷贝
  return *this;
  }
  int *m_age;  
};
void test01()
{
  Person p1(10);
  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();
  system("pause");
  return 0;
}


关系运算符重置

完整代码:


#include <iostream>
#include <string>
using namespace std;
class Person 
{
public:
  Person(string name,int age)
  {
  this->name = name;
  this->age = age;
  }
  //关系运算符==重置
  bool operator==(Person &p)
  {
  if(this->name == p.name && this->age == p.age)  //进行比较
  {
    return true;
  }
  else
  {
    return false;
  }
  }
  //关系运算符!=重置
  bool operator!=(Person &p)
  {
  if(this->name == p.name && this->age == p.age)  //进行比较
  {
    return false;
  }
  else
  {
    return true;
  }
  }
public:
  string name;
  int age;
};
void test01()
{
  Person p1("小王",15);
  Person p2("小王",16);
  if(p1 == p2)
  {
  cout<<"p1与p2相等"<<endl;
  }
  else
  {
  cout<<"p1与p2不相等"<<endl;
  }
  if(p1 != p2)
  {
  cout<<"p1与p2不相等"<<endl;
  }
  else
  {
  cout<<"p1与p2相等"<<endl;
  }
}
int main()
{
  test01();
  system("pause");
  return 0;
}



调用运算符重载

也就是(),又称为仿函数

特点是:没有固定的写法,十分灵活


#include <iostream>
#include <string>
using namespace std;
class Myprint
{
public:
  //()运算符重载也可以叫仿函数,没有固定,十分自由
  void operator()(string name)  //可以只进行输出
  {
  cout<<name<<endl;
  }
};
class Myadd
{
public:
  //仿函数,也可以进行相加返回
  int operator()(int a,int b)
  {
  return a+b;
  }
};
void test01()
{
  Myprint myprint;
  myprint("天天向上");
}
void test02()
{
  Myadd myadd;
  cout<<myadd(100,200)<<endl;
  //匿名函数对象 Myadd(),然后在(100,200)使用仿函数
  cout<<Myadd()(100,200)<<endl;
}
int main()
{
  test02();
  system("pause");
  return 0;
}


相关文章
|
2月前
|
算法 C++ 开发者
【C++运算符重载】深入理解C++中的流运算符 >>和<<重载
【C++运算符重载】深入理解C++中的流运算符 >>和<<重载
38 0
|
3天前
|
编译器 C语言 C++
【C++从练气到飞升】05---运算符重载(二)
【C++从练气到飞升】05---运算符重载(二)
|
3天前
|
编译器 C++
【C++从练气到飞升】05---运算符重载(一)
【C++从练气到飞升】05---运算符重载(一)
|
5天前
|
编译器 C++
【C++】类与对象(运算符重载、const成员、取地址重载)
【C++】类与对象(运算符重载、const成员、取地址重载)
11 2
|
12天前
|
编译器 C++ 索引
【C++类和对象】拷贝构造与赋值运算符重载(下)
【C++类和对象】拷贝构造与赋值运算符重载
|
12天前
|
存储 编译器 C++
【C++类和对象】拷贝构造与赋值运算符重载(上)
【C++类和对象】拷贝构造与赋值运算符重载
|
25天前
|
存储 编译器 C++
【C++成长记】C++入门 | 类和对象(中) |拷贝构造函数、赋值运算符重载、const成员函数、 取地址及const取地址操作符重载
【C++成长记】C++入门 | 类和对象(中) |拷贝构造函数、赋值运算符重载、const成员函数、 取地址及const取地址操作符重载
|
2月前
|
C++
7. C++运算符重载
7. C++运算符重载
23 0
|
2月前
|
安全 中间件 C++
【C++运算符重载】运算符重载的艺术与实践:何时使用以及使用示例
【C++运算符重载】运算符重载的艺术与实践:何时使用以及使用示例
73 5
|
2月前
|
算法 程序员 C语言
【C++ 运算符重载】深入理解C++迭代器中的前置与后置++操作符
【C++ 运算符重载】深入理解C++迭代器中的前置与后置++操作符
46 0