c++操作符過載多檔案形式練習
Array.h
#pragma once
//標頭檔案中宣告的函式,編譯器會自動去各.cpp檔案去匹配物件的具體定義
//標頭檔案中不能包含.cpp檔案,編譯時候會報錯誤,但可以包含其他的.h標頭檔案
//標頭檔案中不能定義函式的具體內容,只可以宣告函式,但可以定義型別,如果型別裡包含函式,就可以直接定義了,也可以先在類宣告,在其他.cpp檔案中定義,編譯器會自動匹配,在其他.cpp檔案中定義時,不僅要包含標頭檔案,還需要帶上作用域
//當你的標頭檔案中呼叫了別的檔案的型別時,一定需要宣告,不然會報錯誤,或者包含別的帶有這個陌生型別宣告的標頭檔案
#include <iostream>
using namespace std;//型別ostream包含在標頭檔案<iostream>中的std作用域中,因此如果類裡宣告有陌生型別時,我們需要宣告,不然編譯器不知道這個型別是什麼
//函式宣告,實現不可以在標頭檔案中寫出
void print1();
void print2();
//友元函式的宣告,具體定義編譯器會從.cpp檔案中幫我們自動匹配
struct test
{
int a;
int b;
void print3()
{
cout << "3333333333333333333333" << endl;
}
};
class Array
{
public:
//友元函式在類裡僅僅是指定訪問許可權的宣告,並非傳統意義上的函式宣告,雖然有的編譯器允許在未宣告的情況下允許呼叫,但最好還是寫出宣告
friend ostream &operator<<(ostream &os, const Array &a);
friend void function(Array &a);
friend test setData(Array &a, test &t);
friend istream &operator>>(istream &in, Array &a);
Array();
Array(int len);
Array(const Array &another);
void setData(int index, int data);
int getData(int index);
int getLen()const;
~Array();
int &operator[](int i)const;
bool operator==(Array &another);
bool operator!=(Array &another);
Array &operator=(Array &another);
private:
int len;
int *p;
};
//友元函式宣告
test setData(Array &a, test &t);
void function(Array &a);
ostream &operator<<(ostream &os, const Array &a);
istream &operator>>(istream &in, Array &a);
Array.cpp
#include "Array.h"
Array::Array()
{
int len = 0;
this->p = NULL;
}
Array::Array(int len)
{
if (len <= 0)
{
cout << "error" << endl;
return;
}
this->len = len;
p = new int[len];
}
//這就是深拷貝,和解構函式一起出現,成對出現,有指標開闢另外一處空間,就需要解構函式去處理那塊空間,也就需要深拷貝函式進行初始化拷貝構造
Array::Array(const Array &another)
{
len = another.len;
p = new int[len];
for (int i = 0; i < len; i++)
{
p[i] = another.p[i];//並把開闢空間的資料拷貝給p指向的空間
}
cout << "array copy" << endl;
}
void Array::setData(int index, int data)
{
if (index<0 || index>len - 1)
{
cout << "error" << endl;
}
p[index] = data;
}
int Array::getData(int index)
{
if (index<0 || index>len - 1)
{
cout << "error" << endl;
}
return p[index];
}
test setData(Array &a, test &t)
{
t.a = a.len;
t.b = a.len;
return t;
}
int Array::getLen()const
{
return this->len;
}
Array::~Array()
{
cout << "~array()" << endl;
delete[] p;
}
void print1()
{
cout << "11111111111111111111" << endl;
}
void print2()
{
cout << "222222222222222222222222222" << endl;
}
void function(Array &a)
{
cout << a.p[0] << endl;
}
int &Array::operator[](int i)const//這只是表面在這個函式的範圍內,物件是不可修改的,當執行完這個函式時,const修飾的效果就不在了
{
return p[i];
}
//使用const修飾物件的時候,就不可以再使用友元函式直接呼叫物件的私有成員變數,因為你呼叫私有成員變數就可以改變它的值了,但物件是被cosnt修飾過的,裡面的成員不可改變
//這時候可以使用類內部的方法來獲得類內部私有成員變數的值,但一定不能在const修飾物件的時候使用友元函式直接呼叫類裡的私有成員變數,是錯誤的
//當使用例:getLen()方法時,此方法隱式的傳入了物件a,即等價於getLen(&a),此時物件是可以修改的,而上級裡我們要求的是物件不可以修改,因此需要在getLen()方法後加const,即getLen()const;
//也就是當這個總函式裡確定物件為const修飾不可改變時,這個函式裡呼叫的任何小函式用到這個物件的也不可以改變,只有當大函式生命週期結束時,修飾效果才結束
ostream &operator<<(ostream &os, const Array &a)
{
for (int i = 0; i < a.getLen(); i++)
{
//在這個函式的作用域裡,os即為cout,因此用os代替cout
os << "a[" << i << "]=" << a[i] << endl;
}
return os;
}
//輸入便需要改變物件,因此一定不要加const修飾
istream &operator>>(istream &in, Array &a)
{
cout << "please input value" << endl;
for (int i = 0; i < a.len; i++)
{
cout << "a[" << i << "]=";
in >> a.p[i];
}
return in;
}
bool Array::operator==(Array &another)
{
for (int i = 0; i < len; i++)
{
if (p[i] != another.p[i])
{
return false;
}
}
return true;
}
bool Array::operator!=(Array &another)
{
int key = 0;
for (int i = 0; i < len; i++)
{
if (p[i] != another.p[i])
{
return true;
}
}
return false;
}
Array &Array::operator=(Array &another)
{
if (this == &another)
{
return *this;
}
if (this->p != NULL)
{
delete[] this->p;
}
this->len = another.len;
this->p = new int[this->len];
for (int i = 0; i < len; i++)
{
this->p[i] = another.p[i];
}
another[1] = 10;//當操作符過載過以後即可以呼叫,在類裡的方法也可以直接呼叫
return *this;
}
main.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "Array.h"
int main()
{
Array a1(10);
int i = 0;
for (i = 0; i < 10; i++)
{
a1.setData(i, 100 - i);
}
Array a2(a1);
/*
//下面的三段程式碼是錯誤的,因為不是呼叫拷貝建構函式,物件a3裡的值與a1完全相同,即a3裡的指標與a1裡的指標指向同一片區域,因此析構時同一塊區域被析構了兩次,所以不可以
//當有深拷貝的時候,不可以直接為物件賦值,除非重寫運算子
Array a3;
a3 = a1;
cout << "a3.p[0]=" << a3.getData(0) << endl;
*/
a1[0] = 1000;
cout << a1;
function(a1);
test t;
t = setData(a1, t);
print1();
print2();
//cin >> a1;
//cout << a1;
if (a1 == a2)
{
cout << "================" << endl;
}
if (a1 != a2)
{
cout << "'\\\\\\\\\\\\\\\\\\\\\\'" << endl;
}
a1 = a2;
return 0;
}