运算符重载限制

一 重载限制

p387

5.表 11.1 中的大多数运算符都可以通过成员或非成员函数进行重载,但下面的运算符只能通过成员
函数进行重载。
=:赋值运算符。
():函数调用运算符。
[]:下标运算符。
->通过指针访问类成员的运算符。

1.1 重载[]

C++ 规定,下标运算符[]必须以成员函数的形式进行重载。该重载函数在类中的声明格式如下:

读写方式:

返回值类型 & operator[ ] (参数);

只读模式:

const 返回值类型 & operator[ ] (参数) const;

返回值类型:为此类类型可以实现链式调用。

1.2 头文件

//
// Created by Biter on 2019/10/24.
//
#include <iostream>
//
// Created by Biter on 2019/10/24.
//
using namespace std;

class Person {
public:

    /**
     * 用来创建 多个 Person对象
     *
     * @param length
     */
    explicit Person(int length = 0);

    /**
     * 列表初始化
     * 
     * @param age 
     * @param name 
     */
    Person(int age, string name);

    /**
     * 初始化一个对象
     * 
     * @param person 
     */
    Person(Person &person);

    ~Person();

public:
    /**
     * 重载 索引运算符
     * @param i 索引
     * @return 此类对象
     */
    Person &operator[](int i);


    /**
     * 重载赋值运算符
     *
     * @param person
     */
    void operator=(Person &person);

    /**
     * 重载赋值运算符
     *
     * @param age 年龄
     */
    void operator=(int age);

    /**
     * 重载赋值运算符,设置名字
     *
     * @param name 名字
     */
    void operator=(string name);

    /**
     * 重载等于判断运算符,赋值对象
     *
     * @param person
     */
    bool operator==(Person &person);

    /**
     * 重载不等于运算符
     * @param person
     */
    bool operator!=(Person &person);

    /**
     * 输出对象的属性值
     */
    void show() const;

private:
    int m_age{};
    string m_name{};
    int m_length{0};
    Person *m_p;
};

1.3 实现文件

//
// Created by Biter on 2019/10/24.
//
#include "Person.h"

Person::Person(int length) : m_length(length) {
    if (length == 0) {
        m_p = nullptr;
    } else {
        std::cout << "创建对象数组" << std::endl;
        m_p = new Person[length];
        std::cout << "创建对象数组 m_age = " << m_age << "; m_name = " << m_name << "; m_p 地址 = " << m_p << std::endl;
    }
}

Person::Person() {
    m_age = 0;
    m_name = "default";
    std::cout << "默认构造函数 m_age = " << m_age << "; m_name = " << m_name << "; 地址 = " << this << std::endl;
}

Person::Person(Person &person) {
    m_age = person.m_age;
    m_name = person.m_name;
    std::cout << "拷贝构造函数 m_age = " << m_age << "; m_name = " << m_name << "; 地址 = " << this << std::endl;
}

Person::Person(int age, const string name) {
    m_age = age;
    m_name = name;
    std::cout << "列表初始化 m_age = " << m_age << "; m_name = " << m_name << "; 地址 = " << this << std::endl;
}

Person::~Person() {
    if (m_p != nullptr) {
        std::cout << "析构函数 m_age = " << m_age << "; m_name = " << m_name << "; m_p 地址 = " << m_p << std::endl;
        delete[]m_p;
        m_p = nullptr;
    } else{
        std::cout << "析构函数 m_age = " << m_age << "; m_name = " << m_name << "; 地址 = " << this << std::endl;
    }

}

void Person::show() const {
    for (int i = 0; i < m_length; i++) {
        std::cout << "Person[" << i << "].m_age = " << m_p[i].m_age << std::endl;
        std::cout << "Person[" << i << "].m_name = " << m_p[i].m_name << std::endl;
    }
}

Person &Person::operator=(const Person &person) {
    this->m_age = person.m_age;
    m_name = person.m_name;
    std::cout << "赋值运算符 = this->m_age = " << this->m_age << "; this->m_name = " << this->m_name << "  ";
    std::cout << "赋值运算符 = person.m_age = " << person.m_age << "; person.m_name = " << person.m_name << "  ";
    return *this;
}

bool Person::operator==(const Person &person) {
    std::cout << "this->m_age = " << this->m_age << "; this->m_name = " << this->m_name << "  ";
    std::cout << "person.m_age = " << person.m_age << "; person.m_name = " << person.m_name << "  ";
    if ((m_age == person.m_age) && (m_name == person.m_name)) {
        return true;
    } else {
        return false;
    }
}

bool Person::operator!=(const Person &person) {
    std::cout << "this->m_age = " << m_age << "; this->m_name = " << this->m_name << "  ";
    std::cout << "person.m_age = " << person.m_age << "; person.m_name = " << person.m_name << "  ";
    if ((this->m_age != person.m_age) || (this->m_name != person.m_name)) {
        return true;
    } else {
        return false;
    }
}

Person &Person::operator[](int i) {
//    m_p[i].m_age = i;
    std::cout << "数组索引运算符" << std::endl;
    return m_p[i];
}

Person &Person::operator=(int age) {
    m_age = age;
    return *this;
}


Person &Person::operator=(string name) {
    m_name = name;
    return *this;
}

ostream &operator<<(ostream &os, const Person &person) {
    os << "m_age = " << person.m_age << "; m_name = " << person.m_name << endl;
    return os;
}

1.4 程序代码

#include "Person.h"

int main() {
    int mArraySize = 2;

    Person myOperator(mArraySize);
    Person person{23, "biter"};

    Person person1(person);
    myOperator[0] = person;

    myOperator[1] = 1;
    myOperator[1] = "binny";


    myOperator.show();

    std::cout << "是否相等?" << (myOperator[0] == myOperator[1]) << std::endl;
    std::cout << "是否不相等?" << (myOperator[0] != myOperator[1]) << std::endl;
    return 0;
}

二 问题

问题未解决。

/**
 * 重载赋值运算符
 *
 * @param person
 */
Person &operator=(const Person &person);

上面这种方式,重载后,m_age输出始终为0m_name为预期的值。

/**
 * 重载赋值运算符
 *
 * @param age 年龄
 */
Person &operator=(int age);

这种重载赋值运算符,m_age为预期的值,m_name为预期的值。

声明部分:

private:
    int m_age;
    string m_name{};
    int m_length{0};

m_age为基本类型,m_namestring类型。

解决方案

[] 优先级高于 = 。myOperator[0] = person;先执行myOperator[0] ,返回这个对象,然后在执行赋值,为myOperator[0] 赋值

out << myOperator[0] << endl;
Person &Person::operator[](int i) {
   //m_p[i].m_age = i;//这条语句,导致我再次调用索引运算符,就把它的值 设置为索引的值了
   return m_p[i];
}
posted @ 2022-03-26 17:00  浪客禅心  阅读(52)  评论(0编辑  收藏  举报