运算符重载和友元函数

来源:互联网 发布:手机变声器软件 编辑:程序博客网 时间:2024/05/22 06:31

运算符重载

1.概念

  • 什么是运算符重载

 
所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能,因此,一个函数名就可以用来代表不同功能的函数,也就是”一名多用”。

运算符也可以重载。实际上,我们已经在不知不觉之中使用了运算符重载。例如,大 家都已习惯于用加法运算符”+”对整数、单精度数和双精度数进行加法运算,如5+8, 5.8 +3.67等,其实计算机对整数、单精度数和双精度数的加法操作过程是很不相同的, 但由于C++已经对运算符”+”进行了重载,所以就能适用于int, float, doUble类型的运算。

又如”<<“是C++的位运算中的位移运算符(左移),但在输出操作中又是与流对 象cout 配合使用的流插入运算符,”>>“也是位移运算符(右移),但在输入操作中又是与流对象 cin 配合使用的流提取运算符。这就是运算符重载(operator overloading)。C++系统对”<<“和”>>“进行了重载,用户在不同的场合下使用它们时,作用是不同 的。对”<<“和”>>“的重载处理是放在头文件stream中的。因此,如果要在程序中用”<< “和”>>”作流插入运算符和流提取运算符,必须在本文件模块中包含头文件stream(当然还应当包括”using namespace std“)。 
现在要讨论的问题是:用户能否根据自己的需要对C++已提供的运算符进行重载,赋予它们新的含义,使之一名多用。?

  • 运算符重载入门技术推演 
    • 为什么会用运算符重载机制 
      用复数类举例 
      Complex c3 = c1 + c2; 
      原因 Complex是用户自定义类型,编译器根本不知道如何进行加减.因此编译器给提供了一种机制,让用户自己去完成,自定义类型的加减操作。这个机制就是运算符重载机制
    • 运算符重载的本质是一个函数
#include <iostream>using namespace std;class Complex{public:    int a;    int b;public:    Complex(int a=0, int b=0)    {        this->a = a;        this->b = b;    }    void printCom()    {        cout<<a<<" + " << b << "i" <<endl;    }};//1 定义了全局函数Complex myAdd(Complex &c1, Complex &c2){    Complex tmp(c1.a + c2.a, c1.b+ c2.b);    return tmp; //}//2 函数名 升级Complex operator+(Complex &c1, Complex &c2){    cout<<"12345上山 打老虎"<<endl;    Complex tmp(c1.a + c2.a, c1.b+ c2.b);    return tmp; //}int main(){    int a = 0, b = 0;    int c;    c = a + b; //1 基础数据类型 编译器已经知道了. 如何运算    // a + bi 复数运算规则    Complex c1(1, 2), c2(3, 4);    Complex c3; //2 类 也是一种数据类型  用户自定义数据类型 C++编译器 是不知道如何进行运算    //c3 = c1 + c2 ;    //c1--; --c1    //3 c++编译器应该给我们程序员提供一种机制 ...    //让自定义数据类型 有机会 进行 运算符操作 ====> 运算符重载机制    //4 运算符重载机制    //步骤1 普通函数    //Complex c4 = myAdd(c1, c2);    //c4.printCom();    //步骤2 operator+ 函数名称 //Complex c4  = c1 + c2    //Complex c4 = operator+(c1, c2);    //c4.printCom();    //步骤3 +替换 函数名    Complex c4 = c1 + c2;    c4.printCom();    //步骤3    //Complex c4 = c1 / c2;    //c4.printCom();    //总结: 1 运算符重载的本质 是 函数调用    cout<<"hello..."<<endl;    return 1;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

2.限制

3.基础

例如:

    //全局函数 完成 +操作符 重载Complex operator+(Complex &c1, Complex &c2)//类成员函数 完成 -操作符 重载Complex operator-(Complex &c2)
  • 1
  • 2
  • 3
  • 4
  • 运算符重载的两种方法

例如1:通过类成员函数完成-操作符重载

//函数声明 Complex operator-(Complex &c2)//函数调用分析//用类成员函数实现-运算符重载    Complex c4 = c1 - c2;    c4.printCom();    //c1.operator-(c2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

例如2:通过全局函数方法完成+操作符重载

//函数声明 Complex operator+(Complex &c1, Complex &c2) //函数调用分析int main(){        Complex c1(1, 2), c2(3, 4);        //Complex c31 = operator+(c1, c2);Complex c3 = c1 + c2; c3.printCom();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

例如3

//前置++操作符 用全局函数实现 Complex& operator++(Complex &c1) {    c1.a ++;       c1.b ++;    return c1;  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

//调用方法 
++c1 ; //=需要写出操作符重载函数原形 
c1.printCom();

//运算符重载函数名定义 
//首先承认操作符重载是一个函数 定义函数名operator++ 
//分析函数参数 根据左右操作数的个数,operator++(Complex &c1) 
//分析函数返回值Complex& operator++(Complex &c1) 返回它自身

例如4

//4.1前置—操作符 成员函数实现Complex& operator--(){    this->a--;    this->b--;    return *this;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

//4.2调用方法 
--c1; 
c1.printCom();
 
//4.3前置—运算符重载函数名定义 
//c1.operator–()

例如5

    //5.1 //后置++ 操作符 用全局函数实现Complex operator++(Complex &c1, int) {    Complex tmp = c1;    c1.a++;    c1.b++;    return tmp;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

//5.2 调用方法 
c1 ++ ; //先使用 后++ 
//5.3 后置++运算符重载函数名定义 
Complex operator++(Complex &c1, int)

函数占位参数 和 前置++ 相区别

例如6

//6.1 后置— 操作符 用类成员函数实现    Complex operator--(int)     {        Complex tmp = *this;        this->a--;        this->b--;        return tmp;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

//6.2 调用方法 
c1 ++ ; //先使用 后++ 
//6.3 后置–运算符重载函数名定义 
Complex operator--(int) //函数占位参数 和 前置– 相区别

前置和后置运算符总结 
C++中通过一个占位参数来区分前置运算和后置运算

#include <iostream>using namespace std;class Complex{private:    int a;    int b;    //全局函数 重载+运算符    friend Complex operator+(Complex &c1, Complex &c2);    //重载 前置++    friend Complex& operator++(Complex &c1);    friend Complex operator++(Complex &c1, int);public:    Complex(int a=0, int b=0)    {        this->a = a;        this->b = b;    }    void printCom()    {        cout<<a<<" + " << b << "i" <<endl;    }public:    //成员函数法 实现 -运算符重载     Complex operator-(Complex &c2)    {        Complex tmp(this->a - c2.a, this->b - c2.b);        return tmp;    }     //前置--    Complex& operator--()    {        this->a --;        this->b --;        return *this;    }    //后置--    Complex operator--(int)    {        Complex tmp = *this;        this->a--;        this->b--;        return tmp;    }};//全局函数法 实现 + 运算符重载Complex operator+(Complex &c1, Complex &c2){    Complex tmp(c1.a + c2.a, c1.b + c2.b);    return tmp;}//前置++Complex& operator++(Complex &c1){    c1.a++;    c1.b++;    return c1;}//后置++Complex operator++(Complex &c1, int){    //先使用 在让c1加加    Complex tmp = c1;    //return c1;    c1.a ++;    c1.b ++;    return tmp;}/*全局函数、类成员函数方法实现运算符重载步骤    1)要承认操作符重载是一个函数,写出函数名称    2)根据操作数,写出函数参数     3)根据业务,完善函数返回值(看函数是返回引用 还是指针 元素),及实现函数业务*/void main(){    Complex c1(1, 2), c2(3, 4);    //1 全局函数法 实现 + 运算符重载    // Complex operator+(Complex &c1, Complex &c2);    Complex c3 = c1 + c2;    c3.printCom();    //2 成员函数 法 实现 -运算符重载    //c1.operator-(c2);    //Complex operator-(Complex &c2)    Complex c4 = c1 - c2;    c4.printCom();    //前置++操作符 用全局函数实现    ++c1;    c1.printCom();    //前置--操作符 成员函数方法    --c1;    c1.printCom();    //Complex& operator++(Complex &c1)    //c1.operator--();    //后置++操作符 用全局函数实现    c1++;    c1.printCom();    //后置--操作符 用成员函数实现    c1--;    c1.printCom();    //c1.operator--()    cout<<"hello..."<<endl;    system("pause");    return ;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122

定义运算符重载函数名的步骤 
全局函数、类成员函数方法实现运算符重载步骤 
1)要承认操作符重载是一个函数,写出函数名称operator+ () 
2)根据操作数,写出函数参数 
3)根据业务,完善函数返回值(看函数是返回引用 还是指针 元素),及实现函数业务

运算符重载的正规写法

#include <iostream>using namespace std;/*class ostream{};*/class Complex{private:    int a;    int b;    //friend void operator<<(ostream &out, Complex &c1);    friend ostream& operator<<(ostream &out, Complex &c1);public:    Complex(int a=0, int b=0)    {        this->a = a;        this->b = b;    }    void printCom()    {        cout<<a<<" + " << b << "i" <<endl;    }public:    //实现 + 运算符重载    Complex operator+(Complex &c2)    {        Complex tmp(a + c2.a, b + c2.b);        return tmp;    }    //前置++    Complex& operator++()    {        a++;        b++;        return *this;    }    //后置++    Complex operator++(int)    {        //先使用 在让c1加加        Complex tmp = *this;        //return c1;        this->a ++;        this->b ++;        return tmp;    }    //成员函数法 实现 -运算符重载     Complex operator-(Complex &c2)    {        Complex tmp(this->a - c2.a, this->b - c2.b);        return tmp;    }     //前置--    Complex& operator--()    {        this->a --;        this->b --;        return *this;    }    //后置--    Complex operator--(int)    {        Complex tmp = *this;        this->a--;        this->b--;        return tmp;    }};void main31(){    Complex c1(1, 2), c2(3, 4);    //1 全局函数法 实现 + 运算符重载    // Complex operator+(Complex &c1, Complex &c2);    Complex c3 = c1 + c2;    c3.printCom();    //2 成员函数 法 实现 -运算符重载    //c1.operator-(c2);    //Complex operator-(Complex &c2)    Complex c4 = c1 - c2;    c4.printCom();    //前置++操作符 用全局函数实现    ++c1;    c1.printCom();    //前置--操作符 成员函数方法    --c1;    c1.printCom();    //Complex& operator++(Complex &c1)    //c1.operator--();    //后置++操作符 用全局函数实现    c1++;    c1.printCom();    //后置--操作符 用成员函数实现    c1--;    c1.printCom();    //c1.operator--()    cout<<"hello..."<<endl;    system("pause");    return ;}/*void operator<<(ostream &out, Complex &c1){    out<<"12345 生活真是苦"<<endl;    out<<c1.a << " + " << c1.b << "i" << endl;}*/ostream& operator<<(ostream &out, Complex &c1){    out<<"12345 生活真是苦"<<endl;    out<<c1.a << " + " << c1.b << "i" << endl;    return out;}void main(){    int a = 10;    Complex c1(1, 2), c2(3, 4);    cout<<a<<endl; //按照数据类型     //1    cout << c1 ;    //2 ostream 类中 添加 成员函数 .operator<<    //ostream    //cout.operator<<(c1);    //2 函数返回值当左值 需要返回一个引用    cout << c1  << "aaddddd";    //    //cout.operator<<(c1) .operator<<("aaddddd");    //void.operator<<("aaddddd");    system("pause");}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156

友元函数实现操作符重载的应用场景

1)友元函数和成员函数选择方法

  • 当无法修改左操作数的类时,使用全局函数进行重载
  • =, [], ()和->操作符只能通过成员函数进行重载

2)用友元函数 重载 << >>操作符

  • istream 和 ostream 是 C++ 的预定义流类
  • cin 是 istream 的对象,cout 是 ostream 的对象
  • 运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
  • 运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
  • 用友员函数重载 << 和 >> ,输出和输入用户自定义的数据类型

a)用全局函数方法实现 << 操作符

ostream& operator<<(ostream &out, Complex &c1){    //out<<"12345,生活真是苦"<<endl;    out<<c1.a<<" + "<<c1.b<<"i "<<endl;    return out;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

//调用方法 
cout<<c1; 
//链式编程支持 
cout<<c1<<"abcc"; 
//cout.operator<<(c1).operator<<("abcd"); 
/函数返回值充当左值 需要返回一个引用

b)类成员函数方法无法实现 << 操作符重载

  • 因无法拿到cout这个类的源码
  • cout.operator<<(c1);

友元函数重载操作符使用注意点 
a) 友员函数重载运算符常用于运算符的左右操作数类型不同的情况 

b)其他

  • 在第一个参数需要隐式转换的情形下,使用友员函数重载运算符是正确的选择
  • 友员函数没有 this 指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换
  • C++中不能用友员函数重载的运算符有 
    = () [] -> 
    友元函数案例vector类
#include <iostream>using namespace std;//为vector类重载流插入运算符和提取运算符 class vector{ public :    vector( int size =1 ) ;           ~vector() ;    int & operator[]( int i ) ;    friend ostream & operator << ( ostream & output , vector & ) ;    friend istream & operator >> ( istream & input, vector & ) ;private :      int * v ;         int len ;};vector::vector( int size ) {     if (size <= 0 || size > 100 )    {         cout << "The size of " << size << " is null !\n" ; abort() ;      }    v = new int[ size ] ;  len = size ;}vector :: ~vector() {     delete[] v ;      len = 0 ; }int &vector::operator[]( int i )        {     if( i >=0 && i < len )  return v[ i ] ;    cout << "The subscript " << i << " is outside !\n" ;  abort() ;}ostream & operator << ( ostream & output, vector & ary ){     for(int i = 0 ; i < ary.len ; i ++ )          output << ary[ i ] << "  " ;    output << endl ;    return output ;}istream & operator >> ( istream & input, vector & ary ) {     for( int i = 0 ; i < ary.len ; i ++ )          input >> ary[ i ] ;    return  input ;}void main(){     int k ;    cout << "Input the length of vector A :\n" ;         cin >> k ;    vector A( k ) ;    cout << "Input the elements of vector A :\n" ;         cin >> A ;    cout << "Output the elements of vector A :\n" ;    cout << A ;    system("pause");}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

4.提高

1.运算符重载机制 
编译器实现运算符重载实际上就是通过函数重载实现的,可分为全局函数方式,也可分为成员函数方式进行重载,并没有改变原操作符的属性和语义。只是针对某个特定类定义一种新的数据类型操作。

2.重载赋值运算符

  • 赋值运算符重载用于对象数据的复制
  • operator= 必须重载为成员函数
  • 重载函数原型为: 
    类型 & 类名 :: operator= ( const 类名 & ) ;

结论: 
1 先释放旧的内存 
2 返回一个引用 
3 =操作符 从右向左

#define  _CRT_SECURE_NO_WARNINGS #include <iostream>using namespace std;//class  Name{public:    Name(const char *myp)    {        m_len = strlen(myp);        m_p =(char *) malloc(m_len + 1); //        strcpy(m_p, myp);    }    //Name obj2 = obj1;    //解决方案: 手工的编写拷贝构造函数 使用深copy    Name(const Name& obj1)    {        m_len = obj1.m_len;        m_p = (char *)malloc(m_len + 1);        strcpy(m_p, obj1.m_p);    }    //obj3 = obj1;  // C++编译器提供的 等号操作 也属 浅拷贝    //obj3.operator=(obj1)    Name& operator=(Name &obj1)    {        //先释放旧的内存        if (this->m_p != NULL)        {            delete[] m_p;            m_len = 0;        }        //2 根据obj1分配内存大小        this->m_len = obj1.m_len;        this->m_p = new char [m_len+1];        //把obj1赋值        strcpy(m_p, obj1.m_p);        return *this;    }    ~Name()    {        if (m_p != NULL)        {            free(m_p);            m_p = NULL;            m_len = 0;        }    }protected:private:    char *m_p ;    int m_len; };//对象析构的时候 出现coredumpvoid objplaymain(){    Name obj1("abcdefg");    Name obj2 = obj1;  //C++编译器提供的 默认的copy构造函数  浅拷贝    Name obj3("obj3");    obj3 = obj1;  // C++编译器提供的 等号操作 也属 浅拷贝    //obj3.operator=(obj1)    //operato=(Name &obj1)    obj1 = obj2 = obj3;    //obj2.operator=(obj3);    //obj1 = void;}void main(){    objplaymain();    cout<<"hello..."<<endl;    system("pause");    return ;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

3.重载下标运算符

  • [ ]运算符用于访问数据对象的元素
  • 重载格式 类型 类 :: operator[] ( 类型 ) ;
  • 只能用成员函数重载,不能用友元函数重载

示例: 
设 x 是类 X 的一个对象,则表达式 
x [ y ] 
可被解释为 
x . operator [ ] ( y )

函数返回值当左值需要返回一个引用!

4.带下标和相等操作符的数组类

  • 类的头文件
#ifndef NEWARRAY_H#define NEWARRAY_H#include <iostream>#include <stdlib.h>class NewArray{public:    NewArray();    NewArray(int _len);    NewArray(const NewArray & obj);    ~NewArray();    void setData(int index,int var);    int getData(int index);    int length();    int& operator[](int i);    NewArray& operator=(NewArray& obj);    bool operator==(NewArray& obj);    bool operator!=(NewArray& obj);private:    int m_len;    int *m_buf;};#endif // NEWARRAY_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 类的实现文件
#include "newarray.h"NewArray::NewArray(){    m_buf = NULL;    m_len = -1;}NewArray::NewArray(int _len){    if(_len < 0)        _len = 0;    m_len = _len;    m_buf = new int[m_len];}NewArray::NewArray(const NewArray & obj){    m_len = obj.m_len;    m_buf = new int[m_len];    for(int i = 0;i < m_len;i++)    {        m_buf[i] = obj.m_buf[i];    }}NewArray::~NewArray(){    if(m_buf != NULL)    {        delete []m_buf;        m_buf = NULL;        m_len = -1;    }}void NewArray::setData(int index,int var){    m_buf[index] = var;}int NewArray::getData(int index){    return  m_buf[index];}int NewArray::length(){    return m_len;}int& NewArray::operator[](int i){    return m_buf[i];}NewArray& NewArray::operator=(NewArray& obj){    if(m_buf != NULL)    {        delete []m_buf;        m_len = -1;        m_buf = NULL;    }    m_len = obj.m_len;    m_buf = new int[m_len];    for(int i = 0;i < m_len;i++)    {        m_buf[i] = obj.m_buf[i];    }    return *this;}bool NewArray::operator==(NewArray& obj){    if(m_len != obj.m_len)    {        return false;    }    for(int i = 0;i < m_len;i++)    {        if(m_buf[i] != obj.m_buf[i])        {            return false;        }    }    return true;}bool NewArray::operator!=(NewArray& obj){    return !((*this) == obj);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 测试文件
#include "newarray.h"using namespace std;int main(){    NewArray  a1(10);    for (int i=0; i<a1.length(); i++)    {        //成员函数方式赋值        a1.setData(i, i);        //下标运算符重载赋值        a1[i] = i;        //函数返回值当左值,需要返回一个引用        //a1.operator [i]    }    cout<<"\na1: ";    for (int i=0; i<a1.length(); i++)    {        //cout<<a1.getData(i)<<" ";//成员函数方式获取元素        //下标运算符方式获取数组元素        cout<<a1[i]<<"\t";    }    cout<<endl;    //赋值运算符重载    NewArray a2 = a1;    cout<<"\na2: ";    for (int i=0; i<a2.length(); i++)    {        cout<<a2.getData(i)<<" ";    }    cout<<endl;    //3    NewArray a3(5);    {        a3 = a1;        a3 = a2 = a1;        cout<<"\na3: ";        for (int i=0; i<a3.length(); i++)        {            cout<<a3[i]<<" ";        }    }    //功能4    if (a3 == a1)    {        printf("\nequal\n");    }    else    {        printf("\nnot equal\n");    }    //a3.operator==(a1);    //bool operator==(Array &a1);    if (a3 != a1)    {        printf("\nnot equal\n");    }    else    {        printf("\nequal\n");    }    //    //a3.operator!=(a1)    // bool operator!=(Array &a1);    cout<<"hello..."<<endl;    return 1;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87

5.重载函数调用运算符

  • () 运算符用于函数调用
  • 重载格式 
    类型 类 :: operator() ( 表达式表 ) ;
  • 只能用成员函数重载,不能用友元函数重载

例1 
设 x 是类 X 的一个对象,则表达式 
x ( arg1, arg2, … ) 
可被解释为 
x . operator () (arg1, arg2, … ) 
案例:

  • 例:用重载()运算符实现数学函数的抽象
#include <iostream>class  F  { public :          double  operator ( )  ( double x ,  double  y ) ;  } ;double  F :: operator ( )  ( double  x ,  double  y )   { return   x * x + y * y ; }void main ( )           { F  f  ;f.getA();    cout << f ( 5.2 , 2.5 ) << endl ;  // f . operator() (5.2, 2.5)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 例3 用重载()运算符实现 pk 成员函数
#include <iostream.h>class  F  { public :          double  memFun ( double x ,  double  y ) ;  } ;double  F :: memFun ( double  x ,  double  y )   { return   x * x + y * y ; }void main ( )           { F  f  ;    cout << f.memFun ( 5.2 , 2.5 ) << endl ;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

6.不建议重载的运算符

理论知识: 
1)&&和||是C++中非常特殊的操作符 
2)&&和||内置实现了短路规则 
3)操作符重载是靠函数重载来完成的 
4)操作数作为函数参数传递 
5)C++的函数参数都会被求值,无法实现短路规则

#include <cstdlib>#include <iostream>using namespace std;class Test{    int i;public:    Test(int i)    {        this->i = i;    }    Test operator+ (const Test& obj)    {        Test ret(0);        cout<<"执行+号重载函数"<<endl;        ret.i = i + obj.i;        return ret;    }    bool operator&& (const Test& obj)    {        cout<<"执行&&重载函数"<<endl;        return i && obj.i;    }};// && 从左向右void main(){    int a1 = 0;    int a2 = 1;    cout<<"注意:&&操作符的结合顺序是从左向右"<<endl;    if( a1 && (a1 + a2) )    {        cout<<"有一个是假,则不在执行下一个表达式的计算"<<endl;    }    Test t1 = 0;    Test t2 = 1;    //if( t1 && (t1 + t2)  )    //t1  && t1.operator+(t2)    // t1.operator&&(  t1.operator+(t2) )       //1 && || 重载他们 不会产生短路效果    if(  (t1 + t2) && t1)    {        //t1.operator+(t2) && t1;        //(t1.operator+(t2)).operator&&(t1);        cout<<"两个函数都被执行了,而且是先执行了+"<<endl;    }    //2 && 运算符的结合性    // 两个逻辑与运算符  在一块的时候, 采去谈 运算符的结合性    // 从左到右    (t1 + t2) && t1 ; 运算结果 && t2)    //if(  (t1 + t2) && t1 && t2)    {        //t1.operator+(t2) && t1;        //(t1.operator+(t2)).operator&&(t1);        cout<<"两个函数都被执行了,而且是先执行了+"<<endl;    }    system("pause");    return ;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

5.字符串类的实现

  • 头文件
#ifndef MYSTRING_H#define MYSTRING_H#include <iostream>using namespace std;#include <stdlib.h>#include <string.h>class MyString{public:    MyString();    MyString(int _len);    MyString(const char *_str);    MyString(const MyString & obj);    ~MyString();    MyString& operator =(const MyString & obj);    MyString& operator =(const char * _str);    bool operator ==(const MyString & obj);    bool operator ==(const char * _str);    bool operator !=(const MyString & obj);    bool operator !=(const char * _str);    bool operator >(const MyString & obj);    bool operator >(const char * _str);    bool operator <(const MyString & obj);    bool operator <(const char * _str);    char& operator [](int index);    friend ostream& operator<<(ostream & out,MyString & obj);    friend istream& operator>>(istream & in,MyString & obj);private:    int m_len;    char *m_str;};#endif // MYSTRING_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 实现文件
#include "mystring.h"MyString::MyString(){    m_len = 0;    m_str = NULL;}MyString::MyString(int _len){    if(_len < 0)        _len = 0;    m_len = _len;    m_str = new char[m_len+1];    memset(m_str,0,m_len);}MyString::MyString(const char *_str){    if(_str == NULL)    {        m_len = 0;        m_str = new char[m_len+1];        strcpy(m_str,"");    }else    {        m_len = strlen(_str);        m_str = new char[m_len+1];        strcpy(m_str,_str);    }}MyString::MyString(const MyString & obj){    m_len = obj.m_len;    m_str = new char[m_len+1];    strcpy(m_str,obj.m_str);}MyString::~MyString(){    if(m_str != NULL)    {        delete []m_str;        m_str = NULL;        m_len = 0;    }}MyString& MyString::operator =(const MyString & obj){    if(m_str != NULL)    {        delete []m_str;        m_str = NULL;        m_len = 0;    }    m_len = obj.m_len;    m_str = new char[m_len+1];    strcpy(m_str,obj.m_str);    return *this;}MyString& MyString::operator =(const char * _str){    if(m_str != NULL)    {        delete []m_str;        m_str = NULL;        m_len = 0;    }    if(_str == NULL)    {        m_len = 0;        m_str = new char[m_len+1];        strcpy(m_str,"");    }else    {        m_len = strlen(_str);        m_str = new char[m_len+1];        strcpy(m_str,_str);    }    return *this;}bool MyString::operator ==(const MyString & obj){    if(m_len != obj.m_len)    {        return false;    }    return !strcmp(m_str,obj.m_str);}bool MyString::operator ==(const char * _str){    if(_str == NULL)    {        if(m_len == 0)        {            return true;        }else{            return false;        }    }else{        if(m_len == strlen(_str)){            return !strcmp(m_str,_str);        }else{            return false;        }    }}bool MyString::operator !=(const MyString & obj){    return !((*this) == obj);}bool MyString::operator !=(const char * _str){    return !((*this) == _str);}bool MyString::operator >(const MyString & obj){    if(strcmp(m_str,obj.m_str) > 0)    {        return true;    }else{        return false;    }}bool MyString::operator >(const char * _str){    if(strcmp(m_str,_str) > 0)    {        return true;    }else{        return false;    }}bool MyString::operator <(const MyString & obj){    if(strcmp(m_str,obj.m_str) < 0)    {        return true;    }else{        return false;    }}bool MyString::operator <(const char * _str){    if(strcmp(m_str,_str) < 0)    {        return true;    }else{        return false;    }}char& MyString::operator [](int index){    return m_str[index];}ostream& operator<<(ostream & out,MyString & obj){    out<<obj.m_str;    return out;}istream& operator>>(istream & in,MyString & obj){    in>>obj.m_str;    return in;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 测试文件
#define _CRT_SECURE_NO_WARNINGS#include "mystring.h"void main01(){    MyString s1;    MyString s2("s2");    MyString s2_2 = NULL;    MyString s3 = s2;    MyString s4 = "s4444444444";    //测试运算符重载 和 重载[]    //=    s4 = s2;    s4 = "s2222";    s4[1] = '4';    printf("%c", s4[1]);    cout<<s4 <<endl;    //ostream& operator<<(ostream &out, MyString &s)    //char& operator[] (int index)    //MyString& operator=(const char *p);    //MyString& operator=(const MyString &s);    cout<<"hello..."<<endl;    system("pause");    return ;}void main02(){    MyString s1;    MyString s2("s2");    MyString s3 = s2;    if (s2 == "aa")    {        printf("相等");    }    else    {        printf("不相等");    }    if (s3 == s2)    {        printf("相等");    }    else    {        printf("不相等");    }}void main03(){    MyString s1;    MyString s2("s2");    MyString s3 = s2;    s3 = "aaa";    if (s3 < "bbbb" )    {        printf("s3 小于 bbbb");    }    else    {        printf("s3 大于 bbbb");    }    MyString s4 = "aaaaffff";    //strcpy(s4.c_str(), "aa111"); //MFC    cout<<s4<<endl;}void main011(){    MyString s1(128);    cout<<"\n请输入字符串(回车结束)";    cin>>s1;    cout<<s1;    system("pause");}int main(){    MyString s1(128);    cout<<"\n请输入字符串(回车结束)";    cin>>s1;    cout<<s1<<endl;    system("pause");    return 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108

总结

  • 操作符重载是C++的强大特性之一
  • 操作符重载的本质是通过函数扩展操作符的语义
  • operator关键字是操作符重载的关键
  • friend关键字可以对函数或类开发访问权限
  • 操作符重载遵循函数重载的规则
  • 操作符重载可以直接使用类的成员函数实现
  • =, [], ()和->操作符只能通过成员函数进行重载
  • ++操作符通过一个int参数进行前置与后置的重载
  • C++中不要重载&&和||操作符

附录:运算符和结合性

友元函数

class A1{public:    A1()    {        a1 = 100;        a2 = 200;    }    int getA1()    {        return this->a1;    }    //声明一个友元函数    friend void setA1(A1 *p, int a1); //这个函数是这个类的好朋友protected:private:    int a1;    int a2;};void setA1(A1 *p, int a1){    p->a1 = a1;}void main(){    A1 mya1;    cout<<mya1.getA1()<<endl;     setA1(&mya1, 300); //通过友元函数 修改A类的私有属性    cout<<mya1.getA1()<<endl;    system("pause");}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

友元函数不属于类的成员函数,所以只在类里面声明,实现的时候不需要加命名空间!

2.友元类

  • 若B类是A类的友员类,则B类的所有成员函数都是A类的友员函数
  • 友员类通常设计为一种对数据操作或类之间传递消息的辅助类 
#include <iostream>using namespace std;class A{public:    friend class B;//B类 是 A的好朋友 ,在B中可以访问A类的私有成员 私有函数    //1 声明的位置 和 public private没有关系    friend void modifyA(A *pA, int _a); //2 函数modifyA 是 类A的好朋友    A(int a=0, int b=0)    {        this->a = a;        this->b = b;    }    int getA()    {        return this->a;    }private:    int a;    int b;};//  void modifyA(A *pA, int _a){    //pA->a = 100;    pA->a = _a;}//class B{public:    void Set(int a)    {        Aobject.a = a;    }    void printB()    {        cout<<Aobject.a <<endl;    }private:    A Aobject;};//为什么设计友元类函数// 1.java--->1.class(字节码) ==》反射机制分析1.class 找到类对象。直接修改类的私有属性。。。//反射机制 成为一种标准。。。。jdk ...sun 做成标准 。。。jdk 的 api函数中有体现 //AOP//2 1.cpp===>汇编// 预编译 编译  连接  生成 。。gcc -E //gcc -s  -//gcc -o 1.exe 1.c // 汇编往会找。。。。很难。。。。//3 开了一个后门 。。。friend/*gcc -E hello.c -o hello.i(预处理)gcc -S hello.i -o hello.s(编译)gcc -c hello.s -o hello.o(汇编)gcc hello.o -o hello(链接)以上四个步骤,可合成一个步骤gcc hello.c -o hello(直接编译链接成可执行目标文件)gcc -c hello.c或gcc -c hello.c -o hello.o(编译生成可重定位目标文件)*/void main(){    B b1;    b1.Set(300);    b1.printB();    system("pause");}void main2101(){    A a1(1, 2);    cout<< a1.getA()<<endl;    modifyA(&a1, 300);    cout<< a1.getA()<<endl;    cout<<"hello..."<<endl;    system("pause");    return ;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

3.设计一个数组类的最初模型

  • 数组类头文件
#ifndef MYARRAY_H#define MYARRAY_H#include <iostream>using namespace std;class MyArray{public:    MyArray();    MyArray(int _len);    MyArray(MyArray & obj);    ~MyArray();    void setData(int index,int var);    int getData(int index);    int length();private:    int m_length;    int *m_space;};#endif // MYARRAY_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 数组类实现文件
#include "myarray.h"MyArray::MyArray(){    m_space = NULL;    m_length = -1;}MyArray::MyArray(int _len){    if(_len < 0)        _len = 0;    m_length = _len;    m_space = new int[m_length];}MyArray::MyArray(MyArray & obj){    this->m_length = obj.m_length;    this->m_space = new int[this->m_length];    for(int i = 0;i < this->m_length;i++)    {        m_space[i] = obj.m_space[i];    }}MyArray::~MyArray(){    if(m_space != NULL){        delete []m_space;        m_space = NULL;        m_length = -1;    }}void MyArray::setData(int index,int var){    m_space[index] = var;}int MyArray::getData(int index){    return m_space[index];}int MyArray::length(){    return m_length;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 测试文件
#include "myarray.h"int main(){    MyArray  a1(10);    for (int i=0; i<a1.length(); i++)    {        a1.setData(i, i);    }    cout<<"\na1: ";    for (int i=0; i<a1.length(); i++)    {        cout<<a1.getData(i)<<" ";    }    cout<<endl;    MyArray a2 = a1;    cout<<"\na2: ";    for (int i=0; i<a2.length(); i++)    {        cout<<a2.getData(i)<<" ";    }    cout<<endl;    cout<<"hello..."<<endl;    return 1;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

4.小结

  • 类通常用关键字class定义。类是数据成员和成员函数的封装。类的实例称为对象。
  • 结构类型用关键字struct定义,是由不同类型数据组成的数据类型。
  • 类成员由private, protected, public决定访问特性。public成员集称为接口。
  • 构造函数在创建和初始化对象时自动调用。析构函数则在对象作用域结束时自动调用。
  • 重载构造函数和复制构造函数提供了创建对象的不同初始化方式。
  • 静态成员是局部于类的成员,提供一种同类对象的共享机制。
  • 友员用关键字friend声明。友员是对类操作的一种辅助手段。一个类的友员可以访问该类各种性质的成员。
  • 链表是一种重要的动态数据结构,可以在程序运行时创建或撤消数据元素。
原创粉丝点击