码迷,mamicode.com
首页 > 编程语言 > 详细

C++之运算符重载

时间:2016-05-13 14:48:02      阅读:311      评论:0      收藏:0      [点我收藏+]

标签:

1.C++运算符重载的概念和语法

所谓重载,就是赋予新的含义。函数重载(Function Overloading)可以让一个函数名有多种功能,在不同情况下进行不同的操作。运算符重载(Operator Overloading)也是一个道理,同一个运算符可以有不同的功能。

实际上,我们已经在不知不觉中使用了运算符重载。例如,"+"号可以对不同类型(int、float 等)的数据进行加法操作;"<<"既是位移运算符,又可以配合 cout 向控制台输出数据。C++已经对这些运算符进行了重载。

C++ 也允许程序员自己重载运算符,这给我们带来了很大的便利。

下面的代码定义了一个复数类,通过运算符重载,用"+"号实现了复数的加法运算:

  1. #include <iostream>
  2. using namespace std;
  3. class complex{
  4. private:
  5. double real; //实部
  6. double imag; //虚部
  7. public:
  8. complex(): real(0.0), imag(0.0){ }
  9. complex(double a, double b): real(a), imag(b){ }
  10. complex operator+(const complex & A)const;
  11. void display()const;
  12. };
  13. //运算符重载
  14. complex complex::operator+(const complex & A)const{
  15. complex B;
  16. B.real = real + A.real;
  17. B.imag = imag + A.imag;
  18. return B;
  19. }
  20. void complex::display()const{
  21. cout<<real<<" + "<<imag<<"i"<<endl;
  22. }
  23. int main(){
  24. complex c1(4.3, 5.8);
  25. complex c2(2.4, 3.7);
  26. complex c3;
  27. c3 = c1 + c2;
  28. c3.display();
  29. return 0;
  30. }
运行结果:
6.7 + 9.5i

上面的代码定义了一个复数类,real 表示实部,imag 表示虚部,第11行声明了运算符重载,第16行进行了定义。认真观察这两行代码,可以发现和函数重载非常类似。

运算符重载的方式就是定义一个函数,在函数体内实现想要的功能,当用到该运算符时,编译器会自动调用这个函数。也就是说,运算符重载是通过函数定义实现的,它本质上是函数重载。

运算符重载的格式为:
返回值类型 operator 运算符名称 (形参表列){
    //TODO:
}
operator 是关键字,专门用于定义重载运算符的函数。例如,要在全局范围内重载"+",实现复数加法运算,可以这样来定义:
  1. complex operator+(const complex &A, const complex &B){
  2. complex C;
  3. C.real = A.real + B.real;
  4. C.imag = A.imag + B.imag;
  5. return C;
  6. }
细心观察就可以发现,函数名由 operator 和操作符组成,上面的”operator+“就是函数名。重载运算符的函数除了函数名有特定的格式,其他地方和普通函数没有区别。

上面的例子中,我们在类 Complex 中重载了运算符"+",该重载只对 Complex 对象有效。当执行c3 = c1 + c2;语句时,编译器检测到"+"号左边("+"号具有左结合性)是一个 Complex 对象,就会调用运算符重载函数,该语句会被转换为:
c1.operator+(c2);
很明显是一个函数调用。

上面的运算符重载还可以有更加简练的定义形式:
  1. complex complex::operator+(const complex & A)const{
  2. return complex(real+A.real, imag+A.imag);
  3. }
return 语句中的complex(real+A.real, imag+A.imag)会创建一个临时对象,它没有对象名,是一个匿名对象。在创建临时对象过程中调用构造函数,return 语句将该临时对象作为函数返回值。

虽然重载运算符所实现的功能完全可以用函数替代,但运算符重载使得程序的书写更加人性化,易于阅读。运算符被重载后,原有的功能仍然保留,没有丧失或改变。通过运算符重载,扩大了C++已有运算符的功能,使之能用于类对象。

重载运算符的规则

C++对运算符重载做了诸多的限制。

1) 首先,并不是所有的运算符都可以重载。能够重载的运算符包括:
+  -  *  /  %  ^  &  |  ~  !  =  <  >  +=  -=  *=  /=  %=  ^=  &=  |=
<<  >>  <<=  >>=  ==  !=  <=  >=  &&  ||  ++  --  ,  ->*  ->  ()  []
new  new[]  delete  delete[]

上述操作符中,[] 是下标操作符,() 是函数调用操作符。自增自减操作符的前置和后置形式都可以重载。长度运算符”sizeof“、条件运算符”: ?“、成员选择符”.“、对象选择符”.*“和域解析操作符”::“不能被重载。

2) 重载不能改变运算符的优先级和结合性。假设上一节的 complex 类中重载了"+"号和"*"号,那么下面代码中:
  1. int main(){
  2. complex c1,c2,c3,c4;
  3. c4 = c1 + c2 * c3;
  4. return 0;
  5. }
c4 = c1 + c2 * c3;语句等同于c4 = c1 + ( c2 * c3 ) ;,乘法的优先级仍然高于加法,而且它们也仍然是二元运算符。

3) 重载不会改变运算符的用法,例如"+"号总是出现在两个操作数之间,重载后也必须如此。

4) 重载运算符的函数不能有默认的参数,否则就改变了运算符操作数的个数,这显然是错误的。


2.C++用全局函数重载运算符

运算符重载函数既可以声明为类的成员函数,也可以声明为所有类之外的全局函数。

运算符重载函数作为类的成员函数

将运算符重载函数声明为类的成员函数时,二元运算符的参数只有一个,一元运算符不需要参数。之所以少一个参数,是因为这个参数是隐含的。

例如,上节的 complex 类中重载了加法运算符:
complex operator+(const complex & A)const;
当执行:
c3 = c1 + c2;
会被转换为:
c3 = c1.operator+(c2);
通过 this 指针隐式的访问 c1 的成员变量。

运算符重载函数作为类的成员函数

将运算符重载函数声明为全局函数时,二元操作符就需要两个参数,一元操作符需要一个参数,而且其中必须有一个参数是对象,好让编译器区分这是程序员自定义的运算符,防止程序员修改用于内置类型的运算符的性质。

例如,下面这样是不对的:
  1. int operator + (int a,int b){
  2. return (a-b);
  3. }
"+"号原来是对两个数相加,现在企图通过重载使它的作用改为两个数相减。 如果允许这样重载的话,那么表达式 4+3 的结果是7还是1呢?显然,这是绝对禁止的。

如果有两个参数,这两个参数可以都是对象,也可以一个是对象,一个是C ++内置类型的数据,如:
  1. complex operator+(int a, complex &c){
  2. return complex(a+c.real, c.imag);
  3. }
它的作用是使一个整数和一个复数相加。

更改上节的 complex 类,用全局运算符重载函数计算复数的和:
  1. #include <iostream>
  2. using namespace std;
  3. class complex{
  4. private:
  5. double real; //实部
  6. double imag; //虚部
  7. public:
  8. complex(): real(0.0), imag(0.0){ }
  9. complex(double a, double b): real(a), imag(b){ }
  10. void display()const{ cout<<real<<" + "<<imag<<"i"<<endl; }
  11. friend complex operator+(const complex &A, const complex &B); //友元函数
  12. };
  13. //全局运算符重载
  14. complex operator+(const complex &A, const complex &B){
  15. complex C;
  16. C.real = A.real + B.real;
  17. C.imag = A.imag + B.imag;
  18. return C;
  19. }
  20. int main(){
  21. complex c1(4.3, 5.8);
  22. complex c2(2.4, 3.7);
  23. complex c3;
  24. c3 = c1 + c2;
  25. c3.display();
  26. return 0;
  27. }
运行结果:
6.7 + 9.5i

因为重载运算符函数要用到 complex 类的私有变量,所以我们将该函数声明为友元函数。当执行:
c3 = c1 + c2;
会被转换为:
c3 = operator+(c1, c2);
最后要说明两点:
  • 只有在极少的情况下才使用既不是类的成员函数也不是友元函数的普通函数,原因是上面提到的,普通函数不能直接访问类的私有成员。
  • 指针操作符“->”、下标操作符“[]”、函数调用操作符“()”和赋值操作符“=”只能以成员函数的形式重载。

3.C++重载>>和<<(输入输出运算符)

在C++中,系统已经对左移运算符“<<”和右移运算符“>>”分别进行了重载,使其能够用于输入输出,但是输入输出的处理对象只能是系统内建的数据类型。系统重载这两个运算符是以系统类成员函数的形式进行的,因此cout<< var语句可以理解为:

cout.operator<<( var )
如果我们自己定义了一种新的数据类型,需要用输入输出运算符去处理,那么就要重载。本节以前面的 complex 类为例说明输入输出运算符的重载。

重载输入运算符>>

下面我们用全局函数的形式重载输入运算符,使它能够读入两个 double 类型的数据,并转换为一个复数,保存到复数对象中:
  1. istream & operator>>(istream & in, complex & A){
  2. in >> A.real >> A.imag;
  3. return in;
  4. }
istream 是输入流,cin 就是 istream 类的对象,后续会讲解。因为重载运算符函数需要用到 complex 类的 private 成员变量,为了方便,我们将这个函数声明为 complex 类的友元函数。声明形式如下:
friend istream & operator>>(istream & in , complex & a);
该函数可以按照如下方式使用:
complex c;
cin>> c;
当输入1.45 2.34↙后,这两个小数就分别成为 complex 对象 c 的实部和虚部了。cin>> c;这一语句其实可以理解为:
operator<<(cin , c);
在重载输入运算符时,采用引用的方式进行参数传递:输入的参数里面包含一个 istream 类的引用,返回值仍然为该引用。这样做的一个明显好处就是可以采用链式输入(也就是连续输入),如下所示:
complex c1, c2, c3;
cin>> c1 >> c2 >> c3;

重载输出运算符<<

同样的,我们也可以模仿上面的方式对输出运算符进行重载,让它能够输出复数。函数在类内部的声明如下:
rriend ostream &(ostream & out, complex & A);
全局函数的实现如下:
  1. ostream & operator<<(ostream & out, complex & A){
  2. out << A.real <<" + "<< A.imag <<" i ";
  3. return out;
  4. }
与 istream 相反,ostream 表示输出流,cout 就是 ostream 类的对象。为了能够直接访问 complex 类的私有成员变量,同样需要将这个函数声明为 complex 类的友元函数。由于采用了引用的方式进行参数传递,该输出运算符重载函数可以实现链式输出。

结合输入输出运算符的重载,重新实现 complex 类:
  1. #include <iostream>
  2. using namespace std;
  3. class complex{
  4. private:
  5. double real; //复数的实部
  6. double imag; //复数的虚部
  7. public:
  8. complex(): real(0.0), imag(0.0){ };
  9. complex(double a, double b): real(a), imag(b){ };
  10. friend complex operator+(const complex & A, const complex & B);
  11. friend complex operator-(const complex & A, const complex & B);
  12. friend complex operator*(const complex & A, const complex & B);
  13. friend complex operator/(const complex & A, const complex & B);
  14. friend istream & operator>>(istream & in, complex & A);
  15. friend ostream & operator<<(ostream & out, complex & A);
  16. };
  17. //重载加法运算符
  18. complex operator+(const complex & A, const complex &B){
  19. complex C;
  20. C.real = A.real + B.real;
  21. C.imag = A.imag + B.imag;
  22. return C;
  23. }
  24. //重载减法运算符
  25. complex operator-(const complex & A, const complex &B){
  26. complex C;
  27. C.real = A.real - B.real;
  28. C.imag = A.imag - B.imag;
  29. return C;
  30. }
  31. //重载乘法运算符
  32. complex operator*(const complex & A, const complex &B){
  33. complex C;
  34. C.real = A.real * B.real - A.imag * B.imag;
  35. C.imag = A.imag * B.real + A.real * B.imag;
  36. return C;
  37. }
  38. //重载除法运算符
  39. complex operator/(const complex & A, const complex & B){
  40. complex C;
  41. double square = A.real * A.real + A.imag * A.imag;
  42. C.real = (A.real * B.real + A.imag * B.imag)/square;
  43. C.imag = (A.imag * B.real - A.real * B.imag)/square;
  44. return C;
  45. }
  46. //重载输入运算符
  47. istream & operator>>(istream & in, complex & A){
  48. in >> A.real >> A.imag;
  49. return in;
  50. }
  51. //重载输出运算符
  52. ostream & operator<<(ostream & out, complex & A){
  53. out << A.real <<" + "<< A.imag <<" i ";;
  54. return out;
  55. }
  56. int main(){
  57. complex c1, c2, c3;
  58. cin>>c1>>c2;
  59. c3 = c1 + c2;
  60. cout<<"c1 + c2 = "<<c3<<endl;
  61. c3 = c1 - c2;
  62. cout<<"c1 - c2 = "<<c3<<endl;
  63. c3 = c1 * c2;
  64. cout<<"c1 * c2 = "<<c3<<endl;
  65. c3 = c1 / c2;
  66. cout<<"c1 / c2 = "<<c3<<endl;
  67. return 0;
  68. }
运行结果:
2.4 3.6 4.8 1.7
c1 + c2 = 7.2 + 5.3 i
c1 - c2 = -2.4 + 1.9 i
c1 * c2 = 5.4 + 21.36 i
c1 / c2 = 0.942308 + 0.705128 i

在本例中,我们均采用全局函数的形式进行运算符重载,这样在输入输出时方便了不少。


4.C++重载[](下标运算符)

前面已经提到,下标操作符[]必须以类的成员函数的形式进行重载。在类中的声明格式如下:

返回值类型 & operator[] (参数)

const 返回值类型 & operator[] (参数)

使用第一种声明方式,操作符重载函数不仅可以访问对象,同时还可以修改对象。使用第二种声明方式,操作符重载函数只能访问而不能修改对象。

默认情况下,通过下标访问数组中的元素并不具有检查边界溢出功能,我们可以通过重载实现该功能。

请看下面的代码:
  1. #include<iostream>
  2. #include<string>
  3. using namespace std;
  4. class Array{
  5. private:
  6. int length;
  7. int * num;
  8. public:
  9. Array(): length(0), num(NULL){ }
  10. Array(int n);
  11. int & operator[](int);
  12. const int & operator[]( int )const;
  13. int getlength() const{ return length; }
  14. };
  15. Array::Array(int n){
  16. num = new int[n];
  17. length = n;
  18. }
  19. int& Array::operator[](int i){
  20. if(i < 0 || i >= length)
  21. throw string("out of bounds");
  22. return num[i];
  23. }
  24. const int & Array::operator[](int i) const{
  25. if(i < 0 || i >= length)
  26. throw string("out of bounds");
  27. return num[i];
  28. }
  29. int main(){
  30. Array A(5);
  31. int i;
  32. try{
  33. for(i = 0; i < A.getlength(); i++)
  34. A[i] = i;
  35. for(i = 0 ;i < 6; i++ )
  36. cout<< A[i] <<endl;
  37. }catch(string s){
  38. cerr<< s <<", i = "<< i <<endl;
  39. }
  40. return 0;
  41. }
运行结果:
0
1
2
3
4
out of bounds, i = 5
本例用到了C++的错误处理机制以及 string 类,后续将会讲解。
本例提供了两个版本的下标运算符重载函数:
  1. int & operator[]( int );
  2. const int & operator[]( int )const;
第一个函数最后不带 const,加上 const 意味着该成员函数是常成员函数,如果第一个函数后面也加上了const,则两个函数仅有返回值不同,编译器不能够区分这是函数重载,会报错。这两个版本的重载函数其实很好理解,第一个能够修改对象,第二个只能访问对象而不能修改对象。

重载下标运算符[]后,“arr[5]”会被转换为:
arr.operator[]( 5 );
最后需要说明的是:即使没有定义 const 版本的重载函数,这段代码也是可以正确运行的,但是非 const 成员函数不能处理 const 对象,所以在编程时通常会提供两个版本的运算符重载函数。


5.C++重载++和--(自增自减运算符)

自增“++”和自减“--”都是一元运算符,它的前置形式和后置形式都可以被重载。请看下面的例子:

  1. #include <iostream>
  2. #include <iomanip>
  3. using namespace std;
  4. class stopwatch{ //秒表
  5. private:
  6. int min; //分钟
  7. int sec; //秒钟
  8. public:
  9. stopwatch(): min(0), sec(0){ }
  10. void setzero(){ min = 0; sec = 0; }
  11. stopwatch run(); // 运行
  12. stopwatch operator++(); //++i,前置形式
  13. stopwatch operator++(int); //i++,后置形式
  14. friend ostream & operator<<( ostream &, const stopwatch &);
  15. };
  16. stopwatch stopwatch::run(){
  17. ++ sec;
  18. if( sec == 60 ){
  19. min ++;
  20. sec = 0;
  21. }
  22. return *this;
  23. }
  24. stopwatch stopwatch::operator++(){
  25. return run();
  26. }
  27. stopwatch stopwatch::operator++(int n){
  28. stopwatch s = *this;
  29. run();
  30. return s;
  31. }
  32. ostream & operator<<( ostream & out, const stopwatch & s){
  33. out<<setfill(‘0‘)<<setw(2)<<s.min<<":"<<setw(2)<<s.sec;
  34. return out;
  35. }
  36. int main(){
  37. stopwatch s1, s2;
  38. s1 = s2 ++;
  39. cout << "s1: "<< s1 <<endl;
  40. cout << "s2: "<< s2 <<endl;
  41. s1.setzero();
  42. s2.setzero();
  43. s1 = ++ s2;
  44. cout << "s1: "<< s1 <<endl;
  45. cout << "s2: "<< s2 <<endl;
  46. return 0;
  47. }
运行结果:
s1: 00:00
s2: 00:01
s1: 00:01
s2: 00:01

上面的代码定义了一个简单的秒表类,min 表示分钟,sec 表示秒钟,setzero() 函数用于秒表清零,run() 函数是用来描述秒针前进一秒的动作,接下来是三个运算符重载函数。

先来看一下 run() 函数的实现,run() 函数一开始让秒针自增,如果此时自增结果等于60了,则应该进位,分钟加1,秒针置零。

operator++() 函数实现自增的前置形式,直接返回 run() 函数运行结果即可。

operator++ (int n) 函数实现自增的后置形式,返回值是对象本身,但是之后再次使用该对象时,对象自增了,所以在该函数的函数体中,先将对象保存,然后调用一次 run() 函数,之后再将先前保存的对象返回。在这个函数中参数n是没有任何意义的,它的存在只是为了区分是前置形式还是后置形式。

自减运算符的重载与上面类似,这里不再赘述。


6.C++重载=(赋值运算符)

和普通变量一样,对象之间也可以相互赋值。赋值运算符“=”可以用来将一个对象拷贝给另一个已经存在的对象。对象之间的赋值是将成员变量依次拷贝,而不是将整个对象的内存按位拷贝。

[举例] 对象之间的赋值:

  1. #include <iostream>
  2. using namespace std;
  3. class Demo{
  4. private:
  5. int a;
  6. int b;
  7. public:
  8. Demo(): a(0), b(0){ }
  9. Demo(int a, int b): a(a), b(b){ }
  10. void display(){ cout<<a<<", "<<b<<endl; }
  11. };
  12. int main(){
  13. Demo obj1, obj2(10, 20);
  14. obj1 = obj2; //对象之间的赋值
  15. obj1.display();
  16. return 0;
  17. }
运行结果:
10, 20

一般情况下,默认的“=”就能满足我们的需求,但是当一个类中包含指针类型的成员变量时,可能会带来问题。请看下面的代码:
  1. #include <iostream>
  2. using namespace std;
  3. class Book{
  4. private:
  5. double price; //书的价格
  6. int *bookmark; //书签
  7. int num; //书签的数量
  8. public:
  9. Book(): price(0.0), bookmark(NULL), num(0){}
  10. Book(double, int*, int);
  11. void setBookmark(int, int); //修改书签
  12. void display();
  13. };
  14. Book::Book(double price, int *bm, int num): price(price), num(num){
  15. int *bmTemp = new int[num];
  16. for(int i=0; i<num; i++){
  17. bmTemp[i] = bm[i];
  18. }
  19. this->bookmark = bmTemp;
  20. }
  21. void Book::setBookmark(int page, int index){
  22. if(index>=num-1){
  23. cout<<"Out of bound!"<<endl;
  24. }else{
  25. bookmark[index] = page;
  26. }
  27. }
  28. void Book::display(){
  29. cout<<"price: "<<price<<endl;
  30. cout<<"bookmarks: ";
  31. for(int i=0; i<num; i++){
  32. if(i==num-1){
  33. cout<<bookmark[i]<<endl;
  34. }else{
  35. cout<<bookmark[i]<<", ";
  36. }
  37. }
  38. }
  39. int main(){
  40. int bookmark[] = { 1, 49, 56, 290 };
  41. Book java, cpp(68.5, bookmark, 4);
  42. cpp.display();
  43. java = cpp; //对象之间赋值
  44. java.setBookmark(100, 2);
  45. cpp.display();
  46. return 0;
  47. }
运行结果:
price: 68.5
bookmarks: 1, 49, 56, 290
price: 68.5
bookmarks: 1, 49, 100, 290

这段代码定义了一个 Book 类,表示一本书,书有价格,也有书签。书签是我们所标记的页码,这些页码中往往包含重要的知识点,记录下这些页码能够方便以后查阅。书签可以有多个,所以需要将它放在 int 型的数组中。setBookmark() 函数用来修改某个书签,display() 函数用来展示书签和价格。

Book 类的构造函数中不是直接接收参数的值,而是根据参数所指向的数组,再创建一个新的数组。这样做的好处是对象有属于自己的数组,在其他地方修改实参所指向的数组不会影响该数组,能够很好的隔离。

在 main() 函数中,我们创建了两个对象 java 和 cpp,并用 cpp 给 java 赋值。两次调用 display() 的结果不同表明,调用 java 对象的 setBookmark( ) 函数影响到了 cpp 对象。这是因为,执行java = cpp;语句时会将 cpp.bookmark 的值复制给 java.bookmark,不同对象的成员变量指向同一个数组,当然会相互影响。

要解决这个问题,就需要重载赋值运算符,如下所示:
  1. Book & Book::operator=(const Book &b){
  2. if( this != &b){
  3. this->price = b.price;
  4. this->num = b.num;
  5. //为bookmark赋值
  6. int *bmTemp = new int[b.num];
  7. for(int i=0; i<b.num; i++){
  8. bmTemp[i] = b.bookmark[i];
  9. }
  10. this->bookmark = bmTemp;
  11. }
  12. return *this;
  13. }
将这个函数放入 Book 类中,再执行java = cpp;语句时,会转换为:
java.operator=(cpp);
在函数体中,this 就指向 java 对象。这样 java 对象也会拥有属于自己的数组,两个对象之间不会再相会影响。

可以发现,重载赋值运算符时,函数的参数和返回值类型都必须是对象的引用。以 Book 类为例来说,赋值运算符重载函数一般有两种原型:
Book & operator=( Book &b );
Book & operator=( const Book &b );
返回值和参数都是 Book 类对象的引用。下面一种原型则规定在赋值时不能修改原来的对象。

赋值运算符重载函数除了能有对象引用这样的参数之外,也能有其它参数。但是其它参数必须给出默认值。如下所示:
Book & operator=(const Book &b, a = 10);

7.C++重载new和delete运算符

内存管理运算符 new、new[]、delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数。一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内存时才会重载。

重载 new 有两种形式:

//以类的成员函数的形式进行重载
void * 类名::operator new ( size_t size ){
    //TODO:
}
//以全局函数的形式进行重载
void * operator new ( size_t size ){
    //TODO:
}
两种重载形式的返回值相同,都是void *类型,并且都有一个参数,为size_t类型。在重载 new 或 new[] 时,无论是作为成员函数还是作为全局函数,它的第一个参数必须是 size_t 类型。size_t 表示的是要分配空间的大小,对于 new[] 的重载函数而言,size_t 则表示所需要分配的所有空间的总和。
size_t 在头文件 <cstdio> 中被定义为typedef unsigned int size_t;,也就是无符号整型。
当然,重载函数也可以有其他参数,但都必须有默认值,并且第一个参数的类型必须是 size_t。

同样的,delete 运算符也有两种重载形式:
//以类的成员函数的形式进行重载
void 类名:: operator delete ( void *ptr){
    //TODO:
}
//以全局函数的形式进行重载
void 类名:: operator delete ( void *ptr){
    //TODO:
}
两种重载形式的返回值都是 void 类型,并且都必须有一个 void 类型的指针作为参数,该指针指向需要释放的内存空间。

当我们以类的成员函数的形式重载了new 和 delete 操作符,其使用方法如下:
  1. C * c = new C; //分配内存空间
  2. //
  3. delete c; //释放内存空间
如果类中没有定义 new 和 delete 的重载函数,那么会自动调用内建的 new 和 delete 运算符。

C++之运算符重载

标签:

原文地址:http://blog.csdn.net/shuimanting520/article/details/51392073

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!