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

猜你喜欢

转载自blog.csdn.net/tulipless/article/details/80586185