运算符重载(一)
一.运算符重载的介绍
运算符重载允许把标准运算符应用于自定义类型的对象
二.运算符重载的作用
直观自然,可以提高程序的可读性
体现了C++的可扩充性
运算符重载仅仅只是语法上的方便,它是另一种函数调用的方式
运算符重载,本质上是函数重载
(函数重载的条件:形参个数顺序类型)
三.运算符重载的注意事项
不能滥用重载
四.运算符重载的实现
1. 成员函数重载
2. 友元函数重载
五.运算符重载规则
1. 运算符重载不允许发明新的运算符
2. 不能改变运算符操作对象的个数
3. 运算符被重载后,其优先级和结合性不会改变
4. 不能重载的运算符:
作用域解析运算符 ::
条件运算符 ?;
直接成员访问运算符 .
类成员指针引用的运算符 .*
sizeof运算符 sizeof
5. 成员函数重载和友元函数重载的选择:
1) 一般情况下,单目运算符最好重载为类的成员函数:双目运算符则最好重载为友元函数
2) 不能重载为友元函数:= ()[ ] ->
3) 类型转换运算符只能以成员函数方式重载
4) 流运算符只能已友元的方式重载
运算符重载(二)
一.++运算符重载
有成员函数和友元函数两种方式
Demo
#ifndef _INTEGER_H_
#define _INTEGER_H_
#include <iostream>
using namespace std;
class Integer
{
public:
Integer();
Integer(int n);
~Integer();
void display() const;
friend Integer& operator++(Integer&i);
friend Integer operator++(Integer&i , int n);
private:
int n_;
};
#include "integer.h"
Integer::Integer ()
{
}
Integer::Integer (intn): n_(n)
{
}
Integer::~Integer ()
{
}
void Integer::display () const
{
cout<< n_ << endl;
}
#if 0
Integer& Integer::operator++()//修改了n_的值,返回值为对象的引用
{
cout<< "++i" << endl;
++n_;
return *this;
}
Integer Integer::operator++(int n) //返回为临时对象
{
cout<< "i++" << endl;
Integertmp(n_);
n_++;
return tmp;
}
#endif
Integer& operator++(Integer&i) //友元函数,在类外定义时,不需要加关键字friend
{
cout<< "friend ++i" <<endl;
++i.n_;
return i; //无this指针
}
Integer operator++(Integer&i , int n)
{
cout<< "friend i++" <<endl;
Integertmp(i.n_ );
i.n_ ++;
return tmp;
}
#endif
#include "integer.h"
int main()
{
Integern1(5);
++n1;
n1.display();
n1++;
n1.display();
return 0;
}
二.!运算符重载
三.赋值运算符重载
String& operator=(const String& other);
String& operator=(const char* str);
(具体见下面String的实现)
运算符重载(三)String类的实现
一.[]运算符重载
有const和 非const两种版本
#ifndef _STRING_H_
#define _STRING_H_
#include "Stringtool.h"
#include <iostream>
using namespace std;
class String
{
public:
String();
~String();
String(char *str);
void display();
String(const String& other);
String& operator=(constString& other);
char& operator[](unsigned int index);
const char& operator[](unsigned int index) const;
private:
char *str_;
};
#endif
#include "String.h"
String::String ()
{
cout<< "construct test" <<endl;
str_ = new char('\0');
}
String::~String ()
{
cout<< "destroy construct test"<< endl;
delete [] str_;
}
String::String (char*str)
{
cout<< "default construct test"<< endl;
int len = strlen(str) + 1;
str_ = new char[len];
memset(str_,0,len);
strcpy(str_,str);
}
void String::display ()
{
cout<< str_ << endl;
}
String::String(constString& other)
{
int len = strlen(other.str_ ) + 1;
str_ = new char [len];
memset(str_,0,len);
strcpy(str_,other.str_);
}
String& String::operator=(const String& other)
{
if(this ==&other)
{
return *this;
}
int len = strlen(other.str_ ) + 1;
delete [] str_;
str_ = new char[len];
memset(str_,0,len);
strcpy(str_,other.str_);
}
char& String::operator[](unsigned int index)
{
//cout << "no const []" << endl;
//return str_[index];
return const_cast<char&>(static_cast<const String&>(*this)[index]);//no const版通过类型转换调用const版
}
const char& String::operator[](unsigned int index) const
{
cout<< " const []" <<endl;
return str_[index];
}
#include "String.h"
int main()
{
String s1;
s1 = "hello";
cout<< s1[1] << endl;
s1[1] = 'E'; //可做左值
s1.display();
const String s2("world");
cout<< s2[2] << endl;
return 0;
}
二.+运算符重载
#ifndef _STRING_H_
#define _STRING_H_
#include <string.h>
#include <iostream>
using namespace std;
class String
{
public:
String();
~String();
String(char *str);
void display();
String(const String& other);
String& operator=(constString& other);
friend String operator+(const String& s1, constString& s2);
private:
char *str_;
};
#include "String.h"
String::String ()
{
cout<< "construct test" <<endl;
str_ = new char('\0');
}
String::~String ()
{
cout<< "destroy construct test"<< endl;
delete [] str_;
}
String::String (char*str)
{
cout<< "default construct test"<< endl;
int len = strlen(str) + 1;
str_ = new char[len];
memset(str_,0,len);
strcpy(str_,str);
}
void String::display ()
{
cout<< str_ << endl;
}
String::String(constString& other)
{
int len = strlen(other.str_ ) + 1;
str_ = new char [len];
memset(str_,0,len);
strcpy(str_,other.str_);
}
String& String::operator=(const String& other)
{
if(this ==&other)
{
return *this;
}
int len = strlen(other.str_ ) + 1;
delete [] str_;
str_ = new char[len];
memset(str_,0,len);
strcpy(str_,other.str_);
}
String operator+(const String& s1, constString& s2)
{
int len = strlen(s1.str_) + strlen(s2.str_ ) + 1;
char *newptr = new char[len];
memset(newptr,0,len);
strcpy(newptr,s1.str_);
strcat(newptr,s2.str_);
Stringtemp(newptr);
return temp;
}
#include "String.h"
int main()
{
String s1("hello");
String s2(" world");
String s3;
s3 = s1 +s2;
s3.display();
return 0;
}
三.+=运算符重载
#ifndef _STRING_H_
#define _STRING_H_
#include <string.h>
#include <iostream>
using namespace std;
class String
{
public:
String();
~String();
String(char *str);
void display();
String(const String& other);
String& operator=(constString& other);
String& operator+=(constString& s);
private:
char *str_;
};
#endif
#include "String.h"
String::String ()
{
cout<< "construct test" <<endl;
str_ = new char('\0');
}
String::~String ()
{
cout<< "destroy construct test"<< endl;
delete [] str_;
}
String::String (char*str)
{
cout<< "default construct test"<< endl;
int len = strlen(str) + 1;
str_ = new char[len];
memset(str_,0,len);
strcpy(str_,str);
}
void String::display ()
{
cout<< str_ << endl;
}
String::String(constString& other)
{
int len = strlen(other.str_ ) + 1;
str_ = new char [len];
memset(str_,0,len);
strcpy(str_,other.str_);
}
String& String::operator=(const String& other)
{
if(this ==&other)
{
return *this;
}
int len = strlen(other.str_ ) + 1;
delete [] str_;
str_ = new char[len];
memset(str_,0,len);
strcpy(str_,other.str_);
}
String& String::operator+=(const String& s)
{
strcat(str_,s.str_);
return *this;
}
#include "String.h"
int main()
{
String s1("hello");
String s2("world");
s2 += s1;
s2.display();
return 0;
}
四.流运算符重载
问题:为什么一定要使用友元函数进行重载?
答:如果是重载双目运算符,使用类的成员函数方式,就只要设置一个参数作为右侧运算量,而左侧运算量就是对象本身了。但 >> 或 << 左侧运算量是cin或cout而不是对象本身,所以不满足后面一点,就只能声明为友元函数了。
<<运算符重载
>>运算符重载
Demo
#ifndef _STRING_H_
#define _STRING_H_
#include <iostream>
using namespace std;
class String
{
public:
String();
~String();
friend ostream& operator<<(ostream&os,const String& str);
friend istream& operator>>(istream&is,String& str);
private:
char *str_;
};
#include "String.h"
String::String ()
{
cout<< "construct test" <<endl;
str_ = new char('\0');
}
String::~String ()
{
cout<< "destroy construct test"<< endl;
delete [] str_;
}
ostream& operator<<(ostream&os,const String& str)
{
os <<str.str_ ;
return os;
}
istream& operator>>(istream&is,String& str)
{
is >>str.str_;
return is;
#if 0
char buffer[1024];
is >>buffer;
int len = strlen(buffer) + 1;
delete [] str.str_;
str.str_ = new char[len];
strcpy(str.str_,buffer);
return is;
#endif
}
#endif
#include "String.h"
int main()
{
Strings;
cin >>s;
cout<< s << endl;
return 0;
}
运算符重载(四)
一.类型转换运算符重载
#ifndef _INTEGER_H_
#define _INTEGER_H_
#include <iostream>
using namespace std;
class Integer
{
public:
Integer();
Integer(int n);
~Integer();
void display() const;
//Integer& operator++();//先自加再使用
//Integer operator++(int i); //先使用再自加,为区别上面,传无意义的形参i
friend Integer& operator++(Integer &i);
friend Integer operator++(Integer &i , int n);
operator int();
private:
int n_;
};
#endif
#include "integer.h"
Integer::Integer ()
{
}
Integer::Integer (intn): n_(n)
{
}
Integer::~Integer ()
{
}
void Integer::display () const
{
cout<< n_ << endl;
}
Integer::operator int()
{
return n_;
}
#include "integer.h"
int main()
{
Integern1(5);
int x = static_cast<int>(n1);
cout<< x << endl;
return 0;
}
二.->运算符重载
三.new/delete
operator new
只分配所要求的空间,不调用相关对象的构造函数
void* operator new(size_t size)
new operator
new操作
调用operatornew分配足够的空间,并调用相关对象的构造函数
placement new
不分配内存,调用构造函数,在已有空间分配
#include <iostream>
#include <stdio.h>
using namespace std;
void *operator new(size_tsize) //全局
{
cout<< "global new" <<endl;
void * p = malloc(size);
return p;
}
class Test
{
public:
Test()
{
cout<< "default construct Test"<< endl;
}
Test(int num):n_(num)
{
cout<< "construct Test" <<endl;
}
~Test()
{
cout<< "destroy Test" <<endl;
}
void * operator new(size_t size)
{
cout<< "operator new" <<endl;
void * p = malloc(size);
return p;
}
void operator delete(void * p)
{
cout<< "operator delete"<< endl;
free(p);
}
void * operator new(size_t size, void*p)
{
cout<< "placement new" <<endl;
return p;
}
private:
int n_;
};
int main()
{
Test *t1 = new Test(5);// new operator+ constructor function 局部优先
delete t1;
char array[100];
Test *t = new (array) Test(5);
return 0;
}