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;
}