天天看點

【期末複習】c++知識點大回顧,八篇文章讓你永不破防(五)(建議收藏)

【期末複習】c++知識點大回顧,八篇文章讓你永不破防(五)(建議收藏)

目錄總覽

c++知識點複習最全整理(一)

c++知識點複習最全整理(二)

c++知識點複習最全整理(三)

c++知識點複習最全整理(四)

c++知識點複習最全整理(五)

c++知識點複習最全整理(六)

c++知識點複習最全整理(七)

c++知識點複習最全整理(八)

目錄

五、運算符重載

1.運算符new,delete介紹

1.1.new申請空間

1.2.delete釋放空間

2.運算符重載

2.1.相關問題

2.2.常見運算符重載示例

五、運算符重載

1.運算符new,delete介紹

1.1.new申請空間

形式:

指針變量 = new<資料類型>[長度]
  •  申請一個整型(int)空間
int *ptr;
ptr = new int;
           
  •  申請一個整型空間并且初始化
int *ptr;
ptr = new int(5);
           
  • 申請長度為20的一維數組,但不能進行初始化
int *p;
p = new int[10];
           

注意:

  • 當配置設定的長度為1個機關時,可以省略方括号裡面的整數。
int *int_ptr = new int;
//等價形式
int *int_p = new int[1];
           
  • 使用new配置設定空間時,方括号裡面的數值可以是常量,也可以是變量。還可以是數值表達式。
int size = 10;
//常量
int *np = new int[5];
//變量
int *np1 = new int[size];
//表達式
int *np2 = new int[size+10];
           
  •  使用new配置設定的空間是連續的,可以使用指針通路配置設定空間裡面的每一個元素。
int *p = new int[20];

//将第11個元素指派為100
p[10] = 100;
//或者
*(p+10) = 100;
           
  •  如果目前存儲器無法配置設定更多的記憶體空間,new運算符傳回值為0(NULL)

1.2.delete釋放空間

 delete釋放空間隻有兩種形式:

//1
delete p;
//2
delete []p;
           
delete 釋放new配置設定的單個對象指針指向的記憶體
delete[] 釋放new配置設定的對象數組指針指向的記憶體

其實兩種方式差別不大,主要區分在類中展現。

1.針對簡單類型(int,float,long,double,char,struct等)

使用new配置設定後的無論是數組還是非數組形式記憶體空間用兩種方式均可

如:

int *a = new int[10];
 delete a;
 //或delete [] a; 
           

此種情況中的釋放效果相同 原因在于配置設定簡單類型記憶體時,記憶體大小已經确定,系統可以記憶并且進行管理,在析構時,系統并不會調用析構函數,

2.對于類class來說,兩種方式展現出差異。

A *a = new A[10];
delete a;
//僅釋放了a指針指向的全部記憶體空間 但是隻調用了a[0]對象的析構函數 剩下的從a[1]到a[9]這9個使用者對應記憶體空間将不能釋放進而造成記憶體洩漏
delete [] a;
//釋放了a指針指向的全部記憶體空間 并且調用使用類對象的析構函數釋放使用者自己配置設定的記憶體空間
           

注意:

①用new運算符獲得的記憶體空間,隻許使用一次delete,不允許多次對同一塊空間進行多次釋放,否則将會産生嚴重錯誤。

②delete隻能用來釋放由new運算符配置設定的動态記憶體空間,對于程式中的變量、數組的存儲空間,不得使用delete運算符去釋放。

2.運算符重載

運算符重載是通過定義函數實作的,即定義一個重載運算符的函數,在需要執行被重載的運算符時,系統自動調用該函數,以實作相應的運算。

運算符重載實質上是函數的重載。

重載形式:

函數類型 operator 運算符名稱 (形參表列)   { 對運算符的重載處理 }

2.1.相關問題

  • 運算符能否進行重載

可以重載的運算符

+    -    *    /    %    ^    &    |    ~ !    =    <    >    +=    -=    *=    /=    % ^=    &=    |=    <<    >>    >>=    <<=    ==    != <=    >=    &&    ||    ++    --    ->*    ‘    -> []    ()    new    delete    new[]    delete[]

 不能重載的運算符

Operator Name
. 類屬關系運算符 
.* 成員指針運算符 
:: 作用域運算符 
? : 條件運算符 
# 編譯預處理符号 
sizeof() 取資料類型的長度 
  •  運算符重載不能創造新的運算符号,例如不能建立@@表示幂運算
  • 重載的運算符保持運算符的一些性質不變(優先級,結合性,操作個數,文法結構)
  • 指派運算符(=)和位址運算符(&)不需要重載

 運算符重載函數一般采用兩種方式:

  • 成員函數的形式
  • 友元函數的形式

運算符函數是一種特殊的成員函數或友員函數(全局函數通常被指定為友元函數)

2.2.常見運算符重載示例

+,- 運算符,以複數的運算為例:

#include<bits/stdc++.h>
using namespace std;

class Complex
{
private:
    double real,imag;//實部和虛部
public:
    Complex(double r=0,double i=0):real(i),imag(i){}//構造函數
    Complex operator +(const Complex &a);//重載+運算符
    Complex operator -(const Complex &a);//重載-運算符
    void print();
};
//定義為成員函數,可以通路類内的私有變量
Complex Complex::operator +(const Complex&a)
{
    Complex temp(real+a.real,imag+a.imag);
    return temp;
}
Complex Complex::operator -(const Complex&a)
{
    Complex temp(real-a.real,imag-a.imag);
    return temp;
}
void Complex::print()
{
    cout<<real<<" ";
    if(imag!=0)
    {
        if(imag>0) cout<<"+ ";
        cout<<imag<<"i\n";
    }
}
int main()
{
	Complex t1(1,2);
    Complex t2(2,3);
    t2 = t1 + t2;//對象的指派
    t2.print();
	return 0;
}
           

++ ,--重載

#include<bits/stdc++.h>
using namespace std;

class number
{
private:
    int num;
public:
    number(int n=0):num(n){};
    number& operator++();//前置自增
    number operator++(int);//後置自增
    void print();
};
number& number::operator++()
{
    num++;
    return *this;//前置自增要保證先增加,然後傳回增加後的資料,是以傳回類型是引用類型
}
number number::operator++(int)//int為形式參數,不參與實際運算
{
    number temp(*this);//儲存臨時的變量
    num++;//自增1
    return temp;//傳回之前儲存的沒有進行加自增的變量
}
void number::print()
{
    cout<<num<<endl;
}
int main()
{
    number n1(2);
    n1++;
    n1.print();
    ++n1;
    n1.print();
    return 0;
}
           

1、運算符前置自增運算符 , 用成員函數實作時,沒有形式參數。  

2、運算符後置自增運算符 ,另外增加一個形式上的形式參數,類型定為int。

這個參數隻是用來差別兩種自增算符,并不參加實際的運算。

<< 和>>運算符重載

#include<iostream>
using namespace std;
class Complex
{
private:
    double real,imag;
public:
    Complex(double r=0,double i=0):real(r),imag(i){}
    friend istream& operator >> (istream& in,Complex &c);
    friend ostream& operator << (ostream& out,Complex c);
};
istream& operator >> (istream& in,Complex &c)
{
    cout<<"請輸入實部和虛部\n";
    in >> c.real >> c.imag;
    return in;
}
ostream& operator << (ostream& out,Complex c)
{
    if(c.real!=0)
    {
        out << c.real ;//實部輸出
        if(c.imag==0)
        {
            out << 0 << '\n';
            return out;
        }
        else if(c.imag>0)
        {
            out << "+" << c.imag <<"i\n";
            return out;
        }
        else 
        {
            out << c.imag << "i\n";
            return out;
        }
    }
}
int main()
{
	Complex cc;
    cin>>cc;
    cout<<cc;
	return 0;
}
           

3.類型轉換函數(類型轉換運算符)

格式:

operator type(){
    //具體代碼
    return data;
}
           
  • type 是要轉換的目标類型,data 是要傳回的 type 類型的資料。
  • 傳回值data的類型和type目标類型必須是一樣的。

    既然已經知道了要傳回 type 類型的資料,是以沒有必要再像普通函數一樣明确地給出傳回值類型。

  • 類型轉換函數看起來沒有傳回值類型,其實是隐式地指明了傳回值類型。
  • 類型轉換函數也沒有參數,因為要将目前類的對象轉換為其它類型,是以參數不言而喻。
#include <iostream>
using namespace std;

class Complex
{
public:
    Complex(): real(0.0), imag(0.0){ }
    Complex(double real, double imag): real(real), imag(imag){ }
public:
    friend ostream & operator<<(ostream &out, Complex &c);
    //實作兩個複數的相加
    friend Complex operator+(const Complex &c1, const Complex &c2);
    
    operator double() const { return real; }  //類型轉換函數
private:
    double real;  //實部
    double imag;  //虛部
};

//重載>>運算符
ostream & operator<<(ostream &out, Complex &c)
{
    out << c.real <<" + "<< c.imag <<"i";;
    return out;
}
//重載+運算符
Complex operator+(const Complex &c1, const Complex &c2)
{
    Complex c;
    c.real = c1.real + c2.real;
    c.imag = c1.imag + c2.imag;
    return c;
}

int main()
{
    Complex c1(24.6, 100);
    double f = c1;  //相當于 double f = Complex::operator double(&c1);
    cout<<"f = "<<f<<endl;
 
    f = 12.5 + c1 + 6;  //相當于 f = 12.5 + Complex::operator double(&c1) + 6;
    cout<<"f = "<<f<<endl;
 
    int n = Complex(43.2, 9.3);  //先轉換為 double,再轉換為 int
    cout<<"n = "<<n<<endl;

    return 0;
}
           

 運作結果:

f = 24.6
f = 43.1
n = 43
           

注意:

  1. type 可以是内置類型、類類型以及由 typedef 定義的類型别名,任何可作為函數傳回類型的類型(void 除外)都能夠被支援。一般而言,不允許轉換為數組或函數類型,轉換為指針類型或引用類型是可以的。
  2. 類型轉換函數一般不會更改被轉換的對象,是以通常被定義為 const 成員。
  3. 類型轉換函數可以被繼承,可以是虛函數。
  4.  一個類雖然可以有多個類型轉換函數(類似于函數重載),但是如果多個類型轉換函數要轉換的目标類型本身又可以互相轉換(類型相近),那有時候就會産生二義性。例如:
    operator double() const { return m_real; }  //轉換為double類型
    operator int() const { return (int)m_real; }  //轉換為int類型
               
     那麼下面的代碼就會出錯:
    Complex c(12.2, 30);
    float f = 1.1 + c;
               
    編譯器可以調用 operator double() 将 c 轉換為 double 類型,也可以調用 operator int() 将 c 轉換為 int 類型,兩種資料類型都可以和 1.1 進行加法運算。而且從 Complex 轉換為 double 與從 Complex 轉化為 int 是同級關系,沒有誰的優先級是更高的。

也歡迎大家關注我的同名公衆号擷取更多資訊和資料呀(^U^),歡迎大家在留言區交流。

【期末複習】c++知識點大回顧,八篇文章讓你永不破防(五)(建議收藏)