C++ 运算符重载

运算符重载(一)

一.运算符重载的介绍

运算符重载允许把标准运算符应用于自定义类型的对象

 

二.运算符重载的作用

直观自然,可以提高程序的可读性

体现了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;
}


 

 

四.流运算符重载

问题:为什么一定要使用友元函数进行重载

答:如果是重载双目运算符,使用类的成员函数方式,就只要设置一个参数作为右侧运算量,而左侧运算量就是对象本身了。但 >> << 左侧运算量是cincout而不是对象本身,所以不满足后面一点,就只能声明为友元函数了。

<<运算符重载

>>运算符重载

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;
}


  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值