C++學習日記day5
運算子過載
運算子:單目/雙目/三目
過載:(函式過載) 名稱相同,作用不同(“一名多用”)
* 乘號/指標
& 引用/取地址
<<,>> 位移運算子/輸出
. :: ?: *(指標) sizeof
CPoint (3,4)
c1 ,c2; c1+c2
不能改變優先順序,結合性
不能改變所需要的運算元
不能建立新的運算子
單目運算子 ++ – (前置/後置)
前置:
運算子過載本質是一個成員函式;
CPoint c1;
c1++;
成員函式
<返回值> operator <運算子>(<引數列表>)
友元函式
friend <返回值> operator <運算子>(<引數列表>)
friend CPoint operator++(CPoint &c)
單目運算子 ++ – (前置/後置)
int a = 1;
a++ 先賦值 後++ int b = a++;
++a 先++ 後賦值 int b = ++a;
前置:
運算子過載本質是一個成員函式;
CPoint c1;
c1++;
成員函式
<返回值> operator <運算子>(<引數列表>)
CPoint operator++(); (this指標)
friend <返回值> operator <運算子>(<引數列表>)
friend CPoint operator++(CPoint &c)
後置:
成員函式
<返回值> operator <運算子>(<引數列表>)
CPoint operator++(int); (this指標)
int沒有任何實際意義,僅僅是後置單目運算子的標誌
友元函式
friend <返回值> operator <運算子>(<引數列表>)
friend CPoint operator++(CPoint &c,int)
2.實現:先用一箇中介物件儲存原始的值
雙目運算子: + - * /
c = c1+c2
成員函式:
<返回值> operator <運算子>(<引數列表>)
Complex operator+(Complex c2);
引數列表中引數表示右運算元,左運算元用this指標操作
友元函式:
friend Complex operator+(Complex c1,Complex c2)
用成員函式時候 總會有一個this指標指向其中一個運算元;
用友元函式時候 沒有this指標,需要通過引數列表將所有的運算元傳進去
之前的 ++ – + - * / 所有的運算元都在自己的控制範圍之內
所以友元/成員 都可以使用
成員會省略一個左運算元 如果運算元不在自己的控制範圍,那就不能用成員函式
(友元比較規範,需要幾個運算元就傳幾個進去)
友元函式常用於運算子左右運算元不同的情況
賦值運算子 =
一般情況下,系統為每一個類都生成一個預設的賦值運算子
淺拷貝的問題出在預設建構函式 解決方法:深拷貝(自己寫拷貝構造)
指標懸掛問題出在預設賦值運算子 解決方法:自己過載賦值運算子
注意點:
1不可以用友元過載
2不可以被繼承
3不可以宣告為虛擬函式
成員變數有指標/有賦值操作,需要自己過載賦值運算子
陣列下標運算子 []
不能使用友元過載
#include <iostream>
using namespace std;
class myArray
{
private:
int m_length;
int *m_space;
public:
myArray(int length);
myArray(const myArray& obj);
~myArray();
public:
void setData(int index, int value);
int getData(int index);
int length();
//函式返回值當左值,需要返回一個引用
//應該返回一個引用(元素本身) 而不是一個值
int& operator[](int i);
//過載=
myArray& operator=(myArray &a1);
};
myArray::myArray(int length)
{
if (length < 0)
{
length = 0;
}
m_length = length;
m_space = new int[m_length];
}
myArray::myArray(const myArray& obj)
{
this->m_length = obj.m_length;
this->m_space = new int[this->m_length]; //分配記憶體空間
for (int i=0; i<m_length; i++) //陣列元素複製
{
this->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 value)
{
m_space[index] = value;
}
int myArray::getData(int index)
{
return m_space[index];
}
int myArray::length()
{
return m_length;
}
int& myArray::operator[](int i)
{
if(i>m_length)
{
cout << "陣列下標越界" << endl;
}
return m_space[i];
}
myArray& myArray::operator=(myArray &a1)
{
if(this->m_space != NULL)
{
delete[] m_space;
m_space = NULL;
m_length = 0;
}
this->m_length = a1.m_length;
this->m_space = new int[m_length];
for (int i=0; i<m_length; i++)
{
//m_space[i] = a1.m_space[i];
m_space[i] = a1[i];
}
return *this;
}
int main()
{
myArray a1(10);
for(int i = 0;i < a1.length();i++)
{
a1.setData(i,i);
}
for (int i=0; i<a1.length(); i++)
{
cout<<a1.getData(i)<<" ";
}
cout<<endl;
myArray a2 = a1;
cout<<"\n列印陣列a2: ";
for (int i=0; i<a2.length(); i++)
{
cout<<a2.getData(i)<<" ";
}
cout<<endl;
myArray a3(5);
a3 = a1;
a3 = a2 = a1;
cout<<"\n列印陣列a3: ";
for (int i=0; i<a3.length(); i++)
{
cout<<a3[i]<<" ";
}
system("pause");
return 0;
}
小test
字串類的編寫:
#include <iostream>
#include <cstring>
using namespace std;
class MyString
{
private:
int m_len;
char *m_p;
public:
MyString(int len = 0);
MyString(const char *p);
MyString(const MyString & str);
~MyString();
public:
MyString & operator = (const char *p);
MyString & operator = (const MyString &str);
char & operator [](const int index);
bool operator == (const char * p) const;
bool operator == (const MyString & str) const;
bool operator != (const char * p) const;
bool operator != (const MyString & str) const;
bool operator < (const char * p) const;
bool operator < (const MyString & str) const;
bool operator > (const char * p) const;
bool operator > (const MyString & str) const;
public:
char *c_str()
{
return m_p;
}
const char *c_str2()
{
return m_p;
}
int length()
{
return m_len;
}
friend ostream & operator << (ostream & out, const MyString & str);
friend istream & operator >> (istream & in, const MyString & str);
};
MyString::MyString(int len)
{
m_len = len;
m_p = new char [m_len + 1];
cout << "1個引數的建構函式被呼叫!" << endl;
}
MyString::MyString(const char * p)
{
if (p == NULL)
{
m_len = 0;
m_p = new char [1];
m_p[0] = '\0';
}
else
{
m_len = strlen(p);
m_p = new char [m_len + 1];
strcpy(m_p, p);
}
cout << "帶有1個常量字串的建構函式被呼叫!" << endl;
}
MyString::MyString(const MyString & str)
{
if (str.m_len == 0)
{
m_len = 0;
m_p = new char [1];
m_p[0] = '\0';
}
else
{
m_len = str.m_len;
m_p = new char [m_len + 1];
strcpy(m_p, str.m_p);
}
cout << "拷貝建構函式被呼叫!" << endl;
}
MyString::~MyString()
{
if (m_p)
{
delete [] m_p;
m_p = NULL;
m_len = 0;
}
cout << "解構函式被呼叫!" << endl;
}
MyString & MyString::operator = (const char * p)
{
if (m_p)
{
delete [] m_p;
}
if (m_p == NULL)
{
m_len = 0;
m_p = new char [1];
m_p[0] = '\0';
}
else
{
m_len = strlen(p);
m_p = new char [m_len + 1];
strcpy(m_p, p);
}
cout << "常量字串賦值函式被呼叫!" << endl;
return *this;
}
MyString & MyString::operator = (const MyString & str)
{
if (m_p)
{
delete [] m_p;
}
if (m_p == NULL)
{
m_len = 0;
m_p = new char [1];
m_p[0] = '\0';
}
else
{
m_len = str.m_len;
m_p = new char [m_len + 1];
strcpy(m_p, str.m_p);
}
cout << "物件賦值函式被呼叫!" << endl;
return *this;
}
char & MyString::operator [](const int index)
{
cout << "陣列下標運算子過載函式被呼叫!" << endl;
return m_p[index];
}
bool MyString::operator == (const char * p) const
{
cout << "常量字串 == 運算子過載函式被呼叫!" << endl;
if (strcmp(m_p, p) == 0)
{
return true;
}
else
{
return false;
}
}
bool MyString::operator == (const MyString & str) const
{
cout << "物件 == 運算子過載函式被呼叫!" << endl;
return m_p == str.m_p;
}
bool MyString::operator != (const char * p) const
{
cout << "常量字串 != 運算子過載函式被呼叫!" << endl;
return !(m_p == p);
}
bool MyString::operator != (const MyString & str) const
{
cout << "物件 != 運算子過載函式被呼叫!" << endl;
return !(m_p == str.m_p);
}
bool MyString::operator < (const char * p) const
{
cout << "常量字串 < 運算子過載函式被呼叫!" << endl;
if (strcmp(m_p, p) < 0)
{
return true;
}
else
{
return false;
}
}
bool MyString::operator < (const MyString & str) const
{
cout << "物件 < 運算子過載函式被呼叫!" << endl;
if (strcmp(m_p, str.m_p) < 0)
{
return true;
}
else
{
return false;
}
}
bool MyString::operator > (const char * p) const
{
cout << "常量字串 > 運算子過載函式被呼叫!" << endl;
if (strcmp(m_p, p) > 0)
{
return true;
}
else
{
return false;
}
}
bool MyString::operator > (const MyString & str) const
{
cout << "物件 < 運算子過載函式被呼叫!" << endl;
if (strcmp(m_p, str.m_p) > 0)
{
return true;
}
else
{
return false;
}
}
ostream & operator << (ostream & out, const MyString & str)
{
out << str.m_p << " ";
return out;
}
istream & operator >> (istream & in, const MyString & str)
{
in >> str.m_p;
return in;
}
int main()
{
MyString str1(5);
cout << "請輸入長度為5的字串:" << endl;
cin >> str1;
cout <<"str1: ";
cout << str1 << endl;
cout << "_______________________________________" << endl;
MyString str2("Hello World!");
cout <<"str2: ";
cout << str2 << endl;
cout << str2[11] << endl;
cout << "_______________________________________" << endl;
MyString str3 = str1;
cout <<"str3: ";
cout << str3 << endl;
cout << "_______________________________________" << endl;
MyString str4;
str4 = str2;
cout <<"str4: ";
cout << str4 << endl;
cout << "_______________________________________" << endl;
cout << "str1 = str2? : "<< (str1 == str3) << endl;
cout << "_______________________________________" << endl;
cout << "str2 = str4? : "<< (str2 != str4) << endl;
cout << "_______________________________________" << endl;
cout << "str1 > str3? : "<< (str1 > str3) << endl;
cout << "_______________________________________" << endl;
cout << "str3 < str4? : "<< (str3 < str4) << endl;
cout << "_______________________________________" << endl;
cout << "str1 = hello? : "<< (str1 == "hello") << endl;
cout << "_______________________________________" << endl;
cout << "str2 = hello? : "<< (str2 != str4) << endl;
cout << "_______________________________________" << endl;
cout << "str1 > hello world? : "<< (str1 > str3) << endl;
cout << "_______________________________________" << endl;
cout << "str3 < hello world? : "<< (str3 < str4) << endl;
cout << "_______________________________________" << endl;
return 0;
}