C++类和对象(中)

目录

[1. 类的默认成员函数](#1. 类的默认成员函数)

[2. 构造函数](#2. 构造函数)

[2.1 核心功能](#2.1 核心功能)

[2.2 关键特点](#2.2 关键特点)

[2.3 示例代码](#2.3 示例代码)

[2.4 自定义类型成员的构造调用](#2.4 自定义类型成员的构造调用)

[3. 析构函数](#3. 析构函数)

[3.1 核心功能](#3.1 核心功能)

[3.2 关键特点](#3.2 关键特点)

[3.3 示例代码](#3.3 示例代码)

[3.4 C 与 C++ 实现 Stack 的对比(构造 / 析构优势)](#3.4 C 与 C++ 实现 Stack 的对比(构造 / 析构优势))

[3.4.1 C++ 实现(自动调用构造 / 析构,无需手动 Init/Destroy)](#3.4.1 C++ 实现(自动调用构造 / 析构,无需手动 Init/Destroy))

[3.4.2 C 实现(需手动调用 Init/Destroy,易遗漏)](#3.4.2 C 实现(需手动调用 Init/Destroy,易遗漏))

[4. 拷贝构造函数](#4. 拷贝构造函数)

[4.1 核心定义](#4.1 核心定义)

[4.2 关键特点](#4.2 关键特点)

[4.3 示例代码](#4.3 示例代码)

基础拷贝构造实现

[深拷贝实现(Stack 类)](#深拷贝实现(Stack 类))

[5. 赋值运算符重载](#5. 赋值运算符重载)

[5.1 运算符重载基础](#5.1 运算符重载基础)

核心定义

关键规则

示例代码

[1. .*的解释](#1. .*的解释)

2.基础运算符重载

3.前置++与后置++,<<与>>的解释

[5.2 赋值运算符重载核心特性](#5.2 赋值运算符重载核心特性)

核心功能

关键特点

示例代码(赋值运算符重载实现)

[5.3 日期类完整实现(运算符重载综合案例)](#5.3 日期类完整实现(运算符重载综合案例))

头文件(Date.h)

实现文件(Date.cpp)

测试文件(Test.cpp)

[6. 取地址运算符重载与 const 成员函数](#6. 取地址运算符重载与 const 成员函数)

[6.1 const 成员函数](#6.1 const 成员函数)

核心定义

关键特点

示例代码


1. 类的默认成员函数

  • 定义:用户未显式实现时,编译器会自动生成的成员函数,共 6 个核心默认成员函数(C++11 后新增移动构造、移动赋值)。
  • 核心分类及功能:
    1. **初始化与清理:**构造函数(初始化对象)、析构函数(清理资源)。
    2. **拷贝与赋值:**拷贝构造函数(用同类对象初始化新对象)、赋值运算符重载(已有对象间拷贝赋值)。
    3. **取地址重载:**普通对象取地址、const 对象取地址(极少手动实现)。
  • 学习核心:明确编译器默认生成函数的行为是否满足需求;不满足时需手动实现。

2. 构造函数

2.1 核心功能

  • 并非开空间创建对象(局部对象空间由栈帧创建),而是对象实例化时自动初始化对象,替代手动调用的Init函数。

2.2 关键特点

  1. 函数名与类名完全相同。
  2. 无返回值(无需写void)。
  3. 对象实例化时编译器自动调用对应构造函数。
  4. 支持函数重载(可定义多个参数不同的构造函数)。
  5. 未显式定义时,编译器生成无参默认构造函数;显式定义后,编译器不再生成。
  6. 默认构造函数分类:无参构造、全缺省构造、编译器默认生成的构造函数(三者互斥,不可同时存在,否则调用歧义)。
  7. 初始化规则:
    • 对内置类型成员变量:初始化不确定(看编译器)。
    • 对自定义类型成员变量:自动调用其默认构造函数;若该成员无默认构造,需用初始化列表解决。

2.3 示例代码

cpp 复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    // 1. 无参构造函数(默认构造之一)
    Date()
    {
        _year = 1;
        _month = 1;
        _day = 1;
    }

    // 2. 带参构造函数(重载)
    Date(int year, int month, int day)
    {
        _year = year;
        _month = month;
        _day = day;
    }

    // 3. 全缺省构造函数(默认构造之一,与无参构造互斥)
    /*Date(int year = 1, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }*/

    void Print()
    {
        cout << _year << "/" << _month << "/" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1; // 调用无参默认构造(若注释无参构造且无全缺省构造,编译报错)
    Date d2(2025, 1, 1); // 调用带参构造
    // Date d3(); // 警告:编译器无法区分是函数声明还是对象实例化

    d1.Print();
    d2.Print();
    return 0;
}

2.4 自定义类型成员的构造调用

cpp 复制代码
#include<iostream>
using namespace std;

typedef int STDataType;
class Stack
{
public:
    Stack(int n = 4) // 全缺省构造(默认构造)
    {
        _a = (STDataType*)malloc(sizeof(STDataType) * n);
        if (nullptr == _a)
        {
            perror("malloc申请空间失败");
            return;
        }
        _capacity = n;
        _top = 0;
    }
private:
    STDataType* _a;
    size_t _capacity;
    size_t _top;
};

// 自定义类型MyQueue包含Stack成员
class MyQueue
{
private:
    Stack pushst; // 编译器默认生成MyQueue构造,自动调用Stack的默认构造
    Stack popst;
};

int main()
{
    MyQueue mq; // 正常初始化,无需手动调用Stack的构造
    return 0;
}

3. 析构函数

3.1 核心功能

  • 并非销毁对象本身(局部对象栈帧结束时自动销毁),而是对象生命周期结束时自动调用,完成对象中资源的清理(如堆空间释放),替代手动调用的Destroy函数。

3.2 关键特点

  1. **函数名:**类名前加~(波浪号)(即取反的意思)。
  2. 无参数、无返回值(无需写void)。
  3. 一个类只能有一个析构函数(不可重载);未显式定义时,编译器生成默认析构函数。
  4. 对象生命周期结束时(如局部对象出作用域),编译器自动调用。
  5. 清理规则:
    • 对内置类型成员:不做处理。
    • 对自定义类型成员:自动调用其析构函数(无论是否显式定义自身析构)。
  6. 实现原则:
    • 无资源申请(如Date类):无需显式实现,用编译器默认析构即可。
    • 有资源申请(如Stack类):必须显式实现,否则导致资源泄漏。
  7. 析构顺序:局部域中多个对象,后定义的先析构。

3.3 示例代码

cpp 复制代码
#include<iostream>
using namespace std;

typedef int STDataType;
class Stack
{
public:
    Stack(int n = 4) // 构造函数:申请资源
    {
        _a = (STDataType*)malloc(sizeof(STDataType) * n);
        if (nullptr == _a)
        {
            perror("malloc申请空间失败");
            return;
        }
        _capacity = n;
        _top = 0;
    }

    ~Stack() // 显式实现析构函数:释放资源
    {
        cout << "~Stack()" << endl;
        free(_a);
        _a = nullptr;
        _top = _capacity = 0;
    }
private:
    STDataType* _a;
    size_t _capacity;
    size_t _top;
};

// 包含Stack成员的MyQueue类
class MyQueue
{
private:
    Stack pushst;
    Stack popst;
    // 编译器默认生成析构,自动调用Stack的析构;显式写析构也会自动调用
    /*~MyQueue()
    {}*/
};

int main()
{
    Stack st; // 出作用域时自动调用~Stack()
    MyQueue mq; // 出作用域时自动调用MyQueue析构,进而调用两个Stack的析构
    return 0;
}

3.4 C 与 C++ 实现 Stack 的对比(构造 / 析构优势)

3.4.1 C++ 实现(自动调用构造 / 析构,无需手动 Init/Destroy)
cpp 复制代码
bool isValid(const char* s) {
    Stack st; // 自动调用Stack构造初始化
    while (*s)
    {
        if (*s == '[' || *s == '(' || *s == '{')
        {
            st.Push(*s);
        }
        else
        {
            if (st.Empty())
                return false;
            char top = st.Top();
            st.Pop();
            if ((*s == ']' && top != '[') || (*s == '}' && top != '{') || (*s == ')' && top != '('))
                return false;
        }
        ++s;
    }
    return st.Empty(); // 出作用域自动调用Stack析构,释放资源
}
3.4.2 C 实现(需手动调用 Init/Destroy,易遗漏)
cpp 复制代码
bool isValid(const char* s) {
    ST st;
    STInit(&st); // 手动初始化
    while (*s)
    {
        if (*s == '[' || *s == '(' || *s == '{')
        {
            STPush(&st, *s);
        }
        else
        {
            if (STEmpty(&st))
            {
                STDestroy(&st); // 异常场景需手动释放,否则泄漏
                return false;
            }
            char top = STTop(&st);
            STPop(&st);
            if ((*s == ']' && top != '[') || (*s == '}' && top != '{') || (*s == ')' && top != '('))
            {
                STDestroy(&st); // 异常场景需手动释放
                return false;
            }
        }
        ++s;
    }
    bool ret = STEmpty(&st);
    STDestroy(&st); // 正常场景手动释放
    return ret;
}

4. 拷贝构造函数

4.1 核心定义

  • 特殊的构造函数,用于用同类已存在的对象初始化新创建的对象(拷贝初始化)。
  • **语法要求:**第一个参数必须是自身类类型的引用,额外参数需有默认值。

4.2 关键特点

  1. 是构造函数的重载形式。
  2. **第一个参数必须为const 类名&(传值方式会引发无穷递归,编译器直接报错);**可含多个参数,但后续参数需有默认值。
  3. 触发场景:自定义类型对象的拷贝行为(传值传参、传值返回、直接拷贝初始化如Date d2(d1))。
  4. 编译器默认生成规则:
    • 内置类型成员:值拷贝(浅拷贝,字节级拷贝)。
    • 自定义类型成员:调用其拷贝构造函数。
  5. 实现原则:
    • 无资源指向(如Date类):用编译器默认拷贝构造即可。
    • 有资源指向(如Stack类):需手动实现深拷贝(拷贝资源本身,而非仅拷贝指针),否则导致双重释放。
    • 含自定义类型成员(如MyQueue类):编译器默认生成的拷贝构造会调用成员的拷贝构造,无需手动实现(前提是成员已实现深拷贝)。
  6. 返回值注意:
    • 传值返回:生成临时对象,调用拷贝构造。
    • 传引用返回:返回对象别名,无拷贝,但需确保返回对象生命周期长于当前函数(避免野引用)。

4.3 示例代码

基础拷贝构造实现
cpp 复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    Date(int year = 1, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }

    // 正确拷贝构造:const引用参数
    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }

    // 错误示例:传值参数,编译报错
    // Date(Date d) {}

    void Print()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

void Func1(Date d) // 传值传参,调用Date拷贝构造
{
    d.Print();
}

int main()
{
    Date d1(2024, 7, 5);
    Date d2(d1); // 拷贝初始化,调用拷贝构造
    Date d3 = d1; // 拷贝初始化,调用拷贝构造
    Func1(d1); // 传值传参,调用拷贝构造

    d2.Print();
    d3.Print();
    return 0;
}
深拷贝实现(Stack 类)
cpp 复制代码
#include<iostream>
#include<cstring>
using namespace std;

typedef int STDataType;
class Stack
{
public:
    Stack(int n = 4)
    {
        _a = (STDataType*)malloc(sizeof(STDataType) * n);
        if (nullptr == _a)
        {
            perror("malloc申请空间失败");
            return;
        }
        _capacity = n;
        _top = 0;
    }

    // 手动实现深拷贝拷贝构造
    Stack(const Stack& st)
    {
        // 为新对象申请独立资源
        _a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
        if (nullptr == _a)
        {
            perror("malloc申请空间失败!!!");
            return;
        }
        // 拷贝资源内容
        memcpy(_a, st._a, sizeof(STDataType) * st._top);
        _top = st._top;
        _capacity = st._capacity;
    }

    void Push(STDataType x)
    {
        if (_top == _capacity)
        {
            int newcapacity = _capacity * 2;
            STDataType* tmp = (STDataType*)realloc(_a, newcapacity * sizeof(STDataType));
            if (tmp == NULL)
            {
                perror("realloc fail");
                return;
            }
            _a = tmp;
            _capacity = newcapacity;
        }
        _a[_top++] = x;
    }

    ~Stack()
    {
        cout << "~Stack()" << endl;
        free(_a);
        _a = nullptr;
        _top = _capacity = 0;
    }
private:
    STDataType* _a;
    size_t _capacity;
    size_t _top;
};

class MyQueue
{
private:
    Stack pushst;
    Stack popst;
};

int main()
{
    Stack st1;
    st1.Push(1);
    st1.Push(2);
    Stack st2 = st1; // 调用深拷贝拷贝构造,st1和st2资源独立

    MyQueue mq1;
    MyQueue mq2 = mq1; // 调用默认拷贝构造,自动调用Stack的深拷贝拷贝构造
    return 0;
}

5. 赋值运算符重载

5.1 运算符重载基础

核心定义
  • 允许为类类型对象重新定义运算符含义,本质是特殊名称的函数(operator+operator==等)。
关键规则
  1. 参数个数:与运算符运算对象数量一致(一元运算符 1 个参数,二元运算符 2 个参数)。
  2. 成员函数重载:左侧运算对象通过this指针隐含传递,参数个数比运算对象少 1。
  3. 优先级与结合性:与内置类型运算符保持一致。
  4. 不可重载的运算符:.*::sizeof?:.(5 个,选择题常考)。
  5. 限制:至少有一个类类型参数,不可改变内置类型运算符含义(如int operator+(int x, int y)编译报错)。
  6. 特殊重载:
    • 前置++与后置++:后置++需增加一个无用int参数,用于区分重载。
    • <<>>:需重载为全局函数(避免this指针抢占左侧运算对象位置),通常通过友元访问类私有成员。
示例代码
1. .*的解释
cpp 复制代码
#include<iostream>
using namespace std;
// 编译报错:"operator +"必须⾄少有⼀个类类型的形参
  int operator+(int x, int y)
{
   return x - y;
}
  class A{
     public:
        void func()
       {
          cout << "A::func()" << endl;
       }
         };
 typedef void(A::*PF)(); //成员函数指针类型
  int main(){

// C++规定成员函数要加&才能取到函数指针
       PF pf = &A::func;
        A obj;//定义ob类对象temp
// 对象调⽤成员函数指针时,使⽤.*运算符
   (obj.*pf)();
         return 0;
 }
2.基础运算符重载
cpp 复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    Date(int year = 1, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }

 // 重载为全局的⾯临对象访问私有成员变量的问题
 // 有⼏种⽅法可以解决:
 // 1、成员放公有
 // 2、Date提供getxxx函数
 // 3、友元函数
 // 4、重载为成员函数

 bool operator==(const Date& d1, const Date& d2)
 {
     return d1._year == d2._year
     && d1._month == d2._month
     && d1._day == d2._day;
 }


    void Print()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2024, 7, 5);
    Date d2(2024, 7, 5);

// 运算符重载函数可以显⽰调⽤
 operator==(d1, d2);

// 编译器会转换成 operator==(d1, d2);
    d1 == d2;
    cout << (d1 == d2) << endl; // 调用d1.operator==(d2)
  
    d1.Print();
    return 0;
}
3.前置++与后置++,<<>>的解释
cpp 复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    Date(int year = 1, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }

    // 成员函数重载==(二元运算符,参数为右侧运算对象)
    bool operator==(const Date& d)
    {
        return _year == d._year
            && _month == d._month
            && _day == d._day;
    }

    // 前置++(一元运算符,无额外参数)
    Date& operator++()
    {
        cout << "前置++" << endl;
        _day++;
        // 需处理日期进位(省略)
        return *this;
    }

    // 后置++(一元运算符,增加int参数区分)
    Date operator++(int)
    {
        Date tmp(*this); // 保存当前状态
        cout << "后置++" << endl;
        _day++;
        // 需处理日期进位(省略)
        return tmp; // 返回修改前的对象
    }

    void Print()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2024, 7, 5);
    Date d2(2024, 7, 5);

    cout << (d1 == d2) << endl; // 调用d1.operator==(d2)
    ++d1; // 调用d1.operator++()
    d1++; // 调用d1.operator++(0)

    d1.Print();
    return 0;
}

5.2 赋值运算符重载核心特性

核心功能
  • 完成两个已存在对象间的拷贝赋值(区别于拷贝构造:拷贝构造用于新对象初始化)。
关键特点
  1. 必须重载为成员函数(C++ 规定)。
  2. 参数建议:const 类名&(避免传值拷贝,提高效率)
  3. 返回值建议:类名&(支持连续赋值,如d1 = d2 = d3,返回*this)。
  4. 编译器默认生成规则:
    • 内置类型成员:值拷贝(浅拷贝)。
    • 自定义类型成员:调用其赋值运算符重载。
  5. 实现原则:
    • 无资源指向(如Date类):用编译器默认实现即可。
    • 有资源指向(如Stack类):需手动实现深拷贝,避免双重释放。
    • 含自定义类型成员(如MyQueue类):编译器默认实现会调用成员的赋值运算符重载,无需手动实现。
  6. 优化点:可添加自赋值检查(if (this != &d)),避免无效拷贝。
示例代码(赋值运算符重载实现)
cpp 复制代码
#include<iostream>
using namespace std;

class Date
{
public:
    Date(int year = 1, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }

    // 拷贝构造(新对象初始化)
    Date(const Date& d)
    {
        cout << "Date(const Date& d)" << endl;
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }

    // 赋值运算符重载(已有对象拷贝)
    Date& operator=(const Date& d)
    {
        // 自赋值检查(可选)
        if (this != &d)
        {
            _year = d._year;
            _month = d._month;
            _day = d._day;
        }
        return *this; // 支持连续赋值
    }

    void Print()
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1(2024, 7, 5);
    Date d2(d1); // 拷贝构造(d2是新对象)

    Date d3(2024, 7, 6);
    d1 = d3; // 赋值运算符重载(d1、d3均已存在)

    Date d4 = d1; // 拷贝构造(d4是新对象,非赋值)
    d4.Print();
    return 0;
}

5.3 日期类完整实现(运算符重载综合案例)

头文件(Date.h)
cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;

class Date
{
    // 友元声明:允许全局函数operator<<和operator>>访问私有成员
    friend ostream& operator<<(ostream& out, const Date& d);
    friend istream& operator>>(istream& in, Date& d);

public:
    Date(int year = 1900, int month = 1, int day = 1);
    void Print() const;

    // 获取当月天数(考虑闰年)
    int GetMonthDay(int year, int month)
    {
        assert(month > 0 && month < 13);
        static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
        {
            return 29;
        }
        return monthDayArray[month];
    }

    // 日期合法性检查
    bool CheckDate();

    // 关系运算符重载
    bool operator<(const Date& d) const;
    bool operator<=(const Date& d) const;
    bool operator>(const Date& d) const;
    bool operator>=(const Date& d) const;
    bool operator==(const Date& d) const;
    bool operator!=(const Date& d) const;

    // 日期加减天数(复合赋值)
    Date& operator+=(int day);
    Date& operator-=(int day);

    // 日期加减天数(普通成员函数)
    Date operator+(int day) const;
    Date operator-(int day) const;

    // 日期减日期(求间隔天数)
    int operator-(const Date& d) const;

    // 自增自减重载
    Date& operator++();       // 前置++
    Date operator++(int);     // 后置++
    Date& operator--();       // 前置--
    Date operator--(int);     // 后置--

private:
    int _year;
    int _month;
    int _day;
};

// 流插入/流提取全局重载
ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);
实现文件(Date.cpp)
cpp 复制代码
#include"Date.h"

// 日期合法性检查
bool Date::CheckDate()
{
    if (_month < 1 || _month > 12
        || _day < 1 || _day > GetMonthDay(_year, _month))
    {
        return false;
    }
    return true;
}

// 构造函数
Date::Date(int year, int month, int day)
{
    _year = year;
    _month = month;
    _day = day;
    if (!CheckDate())
    {
        cout << "日期非法" << endl;
    }
}

// 打印日期
void Date::Print() const
{
    cout << _year << "-" << _month << "-" << _day << endl;
}

// 关系运算符实现
bool Date::operator<(const Date& d) const
{
    if (_year < d._year)
        return true;
    else if (_year == d._year)
    {
        if (_month < d._month)
            return true;
        else if (_month == d._month)
            return _day < d._day;
    }
    return false;
}

bool Date::operator==(const Date& d) const
{
    return _year == d._year
        && _month == d._month
        && _day == d._day;
}

bool Date::operator<=(const Date& d) const
{
    return *this < d || *this == d;
}

bool Date::operator>(const Date& d) const
{
    return !(*this <= d);
}

bool Date::operator>=(const Date& d) const
{
    return !(*this < d);
}

bool Date::operator!=(const Date& d) const
{
    return !(*this == d);
}

// 复合赋值运算符实现
Date& Date::operator+=(int day)
{
    if (day < 0)
        return *this -= -day;

    _day += day;
    while (_day > GetMonthDay(_year, _month))
    {
        _day -= GetMonthDay(_year, _month);
        ++_month;
        if (_month == 13)
        {
            ++_year;
            _month = 1;
        }
    }
    return *this;
}

Date& Date::operator-=(int day)
{
    if (day < 0)
        return *this += -day;

    _day -= day;
    while (_day <= 0)
    {
        --_month;
        if (_month == 0)
        {
            --_year;
            _month = 12;
        }
        _day += GetMonthDay(_year, _month);
    }
    return *this;
}

// 普通加减运算符实现(基于复合赋值,避免代码冗余)
Date Date::operator+(int day) const
{
    Date tmp = *this;
    tmp += day;
    return tmp;
}

Date Date::operator-(int day) const
{
    Date tmp = *this;
    tmp -= day;
    return tmp;
}

// 日期减日期(求间隔天数)
int Date::operator-(const Date& d) const
{
    Date max = *this;
    Date min = d;
    int flag = 1;
    if (*this < d)
    {
        max = d;
        min = *this;
        flag = -1;
    }

    int n = 0;
    while (min != max)
    {
        ++min;
        ++n;
    }
    return n * flag;
}

// 自增自减实现
Date& Date::operator++()
{
    *this += 1;
    return *this;
}

Date Date::operator++(int)
{
    Date tmp(*this);
    *this += 1;
    return tmp;
}

Date& Date::operator--()
{
    *this -= 1;
    return *this;
}

Date Date::operator--(int)
{
    Date tmp(*this);
    *this -= 1;
    return tmp;
}

// 流插入重载
ostream& operator<<(ostream& out, const Date& d)
{
    out << d._year << "年" << d._month << "月" << d._day << "日";
    return out;
}

// 流提取重载
istream& operator>>(istream& in, Date& d)
{
    cout << "请依次输入年月日:>";
    in >> d._year >> d._month >> d._day;
    if (!d.CheckDate())
    {
        cout << "日期非法" << endl;
    }
    return in;
}
测试文件(Test.cpp)
cpp 复制代码
#include"Date.h"

// 测试日期加减
void TestDate1()
{
    Date d1(2024, 4, 14);
    Date d2 = d1 + 30000;
    d1.Print();
    d2.Print();

    Date d3(2024, 4, 14);
    Date d4 = d3 - 5000;
    d3.Print();
    d4.Print();
}

// 测试自增自减
void TestDate2()
{
    Date d1(2024, 4, 14);
    Date d2 = ++d1;
    d1.Print();
    d2.Print();

    Date d3 = d1++;
    d1.Print();
    d3.Print();
}

// 测试日期减日期
void TestDate3()
{
    Date d1(2024, 4, 14);
    Date d2(2034, 4, 14);
    int n = d2 - d1;
    cout << n << endl;
}

// 测试流插入/流提取
void TestDate4()
{
    Date d1(2024, 4, 14);
    Date d2 = d1 + 30000;
    cout << d1 << endl;
    cout << d2 << endl;

    cin >> d1 >> d2;
    cout << d1 << endl << d2 << endl;
}

int main()
{
    TestDate1();
    TestDate2();
    TestDate3();
    TestDate4();
    return 0;
}

6. 取地址运算符重载与 const 成员函数

6.1 const 成员函数

核心定义
  • const修饰的成员函数,const放在参数列表后,实际修饰隐含的this指针(由类名* const this变为const 类名* const this)。
关键特点
  1. 功能限制:函数体内不能修改类的任何成员变量(只读)。
  2. 调用规则:
    • const 对象只能调用 const 成员函数。
    • 非 const 对象可调用 const 成员函数(权限缩小,允许)和非 const 成员函数。
示例代码
cpp 复制代码
class Date
{
public:
    // 普通对象取地址重载
    Date* operator&()
    {
        return this; // 默认行为;可改为return nullptr;隐藏地址
    }

    // const对象取地址重载
    const Date* operator&() const
    {
        return this; // 默认行为;可改为return nullptr;隐藏地址
    }

private:
    int _year;
    int _month;
    int _day;
};
相关推荐
kgduu2 小时前
js之表单
开发语言·前端·javascript
钊兵2 小时前
java实现GeoJSON地理信息对经纬度点的匹配
java·开发语言
毕设源码-钟学长2 小时前
【开题答辩全过程】以 基于Python的健康食谱规划系统的设计与实现为例,包含答辩的问题和答案
开发语言·python
秋刀鱼程序编程2 小时前
Java基础入门(五)----面向对象(上)
java·开发语言
Remember_9932 小时前
【LeetCode精选算法】滑动窗口专题二
java·开发语言·数据结构·算法·leetcode
Filotimo_2 小时前
在java开发中,cron表达式概念
java·开发语言·数据库
码农水水3 小时前
京东Java面试被问:HTTP/2的多路复用和头部压缩实现
java·开发语言·分布式·http·面试·php·wpf
hellokandy3 小时前
C++ 如何知道程序最多可以申请多少内存
c++·vector·cin·cout
你怎么知道我是队长3 小时前
C语言---未定义行为
java·c语言·开发语言