C++——類和對象(中)

文章目錄

  • 一、類的默認成員函數
  • 二、構造函數
  • 三、析構函數
  • 四、拷?構造函數
  • 五、賦值運算符重載
    • 1. 運算符重載
    • 2. 賦值運算符重載
  • 六、取地址運算符重載
    • const成員函數
    • 取地址運算符重載
  • 七、應用:?期類實現
    • Date.h
    • Date.cpp
    • test.cpp

一、類的默認成員函數

默認成員函數就是??沒有顯式實現,編譯器會?動?成的成員函數稱為默認成員函數。

?個類,我們不寫的情況下編譯器會默認?成以下6個默認成員函數,需要注意的是這6個中最重要的是前4個,最后兩個取地址重載不重要,只需要了解

①初始化功能的構造函數
②清理功能的析構函數
③使用同類對象初始化創建對象的拷貝構造
④把一個對象賦值給另一個對象的賦值重載
⑤對普通對象取地址重載
⑥對const對象取地址重載

默認成員函數很重要,也?較復雜,我們要從兩個??去學習:

? 第?:我們不寫時,編譯器默認?成的函數?為是什么,是否滿?我們的需求。
? 第?:編譯器默認?成的函數不滿?我們的需求,我們需要??實現,那么如何??實現?

二、構造函數

構造函數是特殊的成員函數,需要注意的是,構造函數雖然名稱叫構造, 但是構造函數的主要任務并不是開空間創建對象(我們常使?的局部對象是棧幀創建時,空間就開好了),?是對象實例化時初始化對象。

構造函數的特點:

  1. 函數名與類名相同。
  2. ?返回值。(返回值啥都不需要給,也不需要寫void,不要糾結,C++規定如此)
  3. 對象實例化時系統會?動調?對應的構造函數。
  4. 構造函數可以重載。
  5. 如果類中沒有顯式定義構造函數,則C++編譯器會?動?成?個?參的默認構造函數,?旦??顯式定義編譯器將不再?成。
  6. ?參構造函數、全缺省構造函數、我們不寫構造時編譯器默認?成的構造函數,都叫做默認構造函數。但是這三個函數有且只有?個存在,不能同時存在。 ?參構造函數和全缺省構造函數雖然構成函數重載,但是調?時會存在歧義。要注意默認構造函數并非是編譯器默認?成那個叫默認構造,實際上?參構造函數、全缺省構造函數也是默認構造,總結?下就是不傳實參就可以調?的構造就叫默認構造。
  7. 我們不寫,編譯器默認?成的構造,對內置類型成員變量的初始化沒有要求,也就是說是是否初始化是不確定的,看編譯器。對于?定義類型成員變量,要求調?這個成員變量的默認構造函數初始化。如果這個成員變量,沒有默認構造函數,那么就會報錯,我們要初始化這個成員變量,需要?初始化列表才能解決,后面再提到初始化列表。

說明:C++把類型分成內置類型(基本類型)和?定義類型。內置類型就是語?提供的原?數據類型。
如:int/char/double/指針等,?定義類型就是我們使?class/struct等關鍵字??定義的類型。

對于內置類型:

#include <iostream>
using namespace std;class Date
{
public://無參構造函數Date(){_year = 2000;_month = 6;_day = 1;}//帶參構造函數Date(int year, int month, int day){_year = year;_month = month;_day = day;}//全缺省構造函數//與無參構造函數矛盾,這兩個只能用一個/*Date(int year = 2024, int month = 7, 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;d1.print();Date d2(2024, 7, 14);d2.print();return 0;
}

在這里插入圖片描述
對于自定義類型:

#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;
};
// 兩個Stack實現隊列
class MyQueue
{
public://編譯器默認生成MyQueue的構造函數調用了Stack的構造,完成了兩個成員的初始化
private:Stack pushst;Stack popst;
};int main()
{MyQueue mq;return 0;
}

在這里插入圖片描述

三、析構函數

析構函數與構造函數功能相反,析構函數不是完成對對象本?的銷毀,?如局部對象是存在棧幀的,函數結束棧幀銷毀,他就釋放了,不需要我們管,C++規定對象在銷毀時會?動調?析構函數,完成對象中資源的清理釋放?作。
析構函數的功能類?我們之前Stack實現的Destroy功能,?像Date沒有Destroy,其實就是沒有資源需要釋放,所以嚴格說Date是不需要析構函數的。

析構函數的特點:

  1. 析構函數名是在類名前加上字符~。
  2. ?參數?返回值。(這?跟構造類似,也不需要加void)
  3. ?個類只能有?個析構函數。若未顯式定義,系統會?動?成默認的析構函數。
  4. 對象?命周期結束時,系統會?動調?析構函數。
  5. 跟構造函數類似,我們不寫編譯器?動?成的析構函數對內置類型成員不做處理,?定類型成員會調?他的析構函數。
  6. 還需要注意的是我們顯?寫析構函數,對于?定義類型成員也會調?他的析構,也就是說?定義類型成員?論什么情況都會?動調?析構函數。
  7. 如果類中沒有申請資源時,析構函數可以不寫,直接使?編譯器?成的默認析構函數,如Date;如果默認?成的析構就可以?,也就不需要顯?寫析構,如MyQueue;但是有資源申請時,?定要??寫析構,否則會造成資源泄漏,如Stack。
  8. ?個局部域的多個對象,C++規定后定義的先析構。
#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實現隊列
class MyQueue
{
public://編譯器默認生成MyQueue的析構函數調用了Stack的析構,釋放的Stack內部的資源// 顯示寫析構,也會自動調用Stack的析構~MyQueue(){cout << "~MyQueue()" << endl;}
private:Stack pushst;Stack popst;
};int main()
{MyQueue mq;return 0;
}

在這里插入圖片描述

四、拷?構造函數

如果?個構造函數的第?個參數是??類類型的引?,且任何額外的參數都有默認值,則此構造函數也叫做拷?構造函數,也就是說拷?構造是?個特殊的構造函數。

拷?構造的特點:

  1. 拷?構造函數是構造函數的?個重載。
  2. 拷?構造函數的第一個參數必須是類類型對象的引?,使?傳值?式編譯器直接報錯,因為語法邏輯上會引發?窮遞歸調?。
    在這里插入圖片描述
  3. C++規定?定義類型對象進?拷??為必須調?拷?構造,所以這??定義類型傳值傳參和傳值返回都會調?拷?構造完成。
  4. 若未顯式定義拷?構造,編譯器會?成?動?成拷?構造函數。?動?成的拷?構造對內置類型成員變量會完成值拷?/淺拷?(?個字節?個字節的拷?),對?定義類型成員變量會調?他的拷?構造。
  5. 像Date這樣的類成員變量全是內置類型且沒有指向什么資源,編譯器?動?成的拷?構造就可以完成需要的拷?,所以不需要我們顯?實現拷?構造。像Stack這樣的類,雖然也都是內置類型,但是_a指向了資源,編譯器?動?成的拷?構造完成的值拷?/淺拷?不符合我們的需求,所以需要
    我們??實現深拷?(對指向的資源也進?拷?)。像MyQueue這樣的類型內部主要是?定義類型
    Stack成員,編譯器?動?成的拷?構造會調?Stack的拷?構造,也不需要我們顯?實現 MyQueue的拷?構造。這?還有?個?技巧,如果?個類顯?實現了析構并釋放資源,那么他就 需要顯?寫拷?構造,否則就不需要。
  6. 傳值返回會產??個臨時對象調?拷?構造,傳值引?返回,返回的是返回對象的別名(引?),沒 有產?拷?。但是如果返回對象是?個當前函數局部域的局部對象,函數結束就銷毀了,那么使? 引?返回是有問題的,這時的引?相當于?個野引?,類似?個野指針?樣。傳引?返回可以減少拷?,但是?定要確保返回對象,在當前函數結束后還在,才能?引?返回。
#include <iostream>
using namespace std;class Date
{
public://無參構造函數Date(){_year = 2000;_month = 6;_day = 1;}//帶參構造函數Date(int year, int month, int day){_year = year;_month = month;_day = day;}//拷貝構造函數 - 傳值//error C2652: “Date”: 非法的復制構造函數: 第一個參數不應是“Date”/*Date(Date d){}*///拷貝構造函數 - 傳引用Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//這個不是拷貝構造函數,只是一個構造函數Date(Date* d){_year = d->_year;_month = d->_month;_day = d->_day;}void print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}private:int _year;int _month;int _day;
};Date& run()
{Date  tmp(2024, 8, 1);return tmp;
}int main()
{Date d1(2024, 7, 14);//這里可以完成拷?,但是不是拷?構造,只是?個普通的構造Date dk(&d1);dk.print();//這樣寫才是拷?構造,通過同類型的對象初始化構造,而不是指針Date d2(d1);d2.print();//也可以這樣寫,這里也是拷?構造Date d3 = d1;d3.print();// run返回了一個局部對象tmp的引用作為返回值// run函數結束,tmp對象就銷毀了,相當于了一個野引用Date ret = run();ret.print();return 0;
}

在這里插入圖片描述

#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;}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(){free(_a);_a = nullptr;_capacity = 0;_top = 0;cout << "~Stack()" << endl;}Stack(const Stack& st){cout << "Stack(const Stack& st)" << endl;// 需要對_a指向資源創建同樣大的資源再拷貝值_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;}
private:STDataType* _a;size_t _capacity;size_t _top;
};// 兩個Stack實現隊列
class MyQueue
{
public:
private:Stack pushst;Stack popst;
};
int main()
{Stack st1;st1.Push(1);st1.Push(2);// Stack不顯示實現拷?構造,用自動生成的拷?構造完成淺拷?// 會導致st1和st2里面的_a指針指向同一塊資源,析構時會析構兩次,程序崩潰Stack st2 = st1;MyQueue mq1;// MyQueue自動生成的拷?構造,會自動調用Stack拷?構造完成pushst/popst// 的拷?,只要Stack拷?構造自己實現了深拷?,他就沒問題MyQueue mq2 = mq1;return 0;
}

在這里插入圖片描述

五、賦值運算符重載

1. 運算符重載

? 當運算符被?于類類型的對象時,C++語?允許我們通過運算符重載的形式指定新的含義。C++規定類類型對象使?運算符時,必須轉換成調?對應運算符重載,若沒有對應的運算符重載,則會編譯報錯。

? 運算符重載是具有特殊名字的函數,他的名字是由operator和后?要定義的運算符共同構成。和其他函數?樣,它也具有其返回類型和參數列表以及函數體。

? 重載運算符函數的參數個數和該運算符作?的運算對象數量?樣多。?元運算符有?個參數,?元運算符有兩個參數,?元運算符的左側運算對象傳給第?個參數,右側運算對象傳給第?個參數。

? 如果?個重載運算符函數是成員函數,則它的第?個運算對象默認傳給隱式的this指針,因此運算符重載作為成員函數時,參數?運算對象少?個。

? 運算符重載以后,其優先級和結合性與對應的內置類型運算符保持?致。

? 不能通過連接語法中沒有的符號來創建新的操作符:?如operator@。

? 注意以下5個運算符不能重載。
在這里插入圖片描述

? 重載操作符?少有?個類類型參數,不能通過運算符重載改變內置類型對象的含義,如: int operator+(int x, int y)

? ?個類需要重載哪些運算符,是看哪些運算符重載后有意義,?如Date類重載operator-就有意義,但是重載operator+就沒有意義。

? 重載++運算符時,有前置++和后置++,運算符重載函數名都是operator++,?法很好的區分。
C++規定,后置++重載時,增加?個int形參,跟前置++構成函數重載,?便區分。

? 重載<<和>>時,需要重載為全局函數,因為重載為成員函數,this指針默認搶占了第?個形參位置,第?個形參位置是左側運算對象,調?時就變成了對象<<cout,不符合使?習慣和可讀性。
重載為全局函數把ostream/istream放到第?個形參位置就可以了,第?個形參位置當類類型對象。

#include <iostream>
using namespace std;class Date
{
public://無參構造函數Date(){_year = 2000;_month = 6;_day = 1;}//帶參構造函數Date(int year, int month, int day){_year = year;_month = month;_day = day;}bool operator==(Date& d){return _year == d._year && _month == d._month && _day == d._day;}//++dDate& operator++(){cout << "前置++" << endl;//...return *this;}//d++Date operator++(int){cout << "后置++" << endl;Date tmp = *this;//...return tmp;}void print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d1;d1.print();Date d2(2024, 7, 14);d2.print();//運算符重載函數可以顯示調用d1.operator==(d2);//編譯器會轉換成 d1.operator==(d2);d1 == d2;cout << (d1 == d2) << endl;//編譯器會轉換成 d1.operator++();++d1;//編譯器會轉換成 d2.operator++(0);d2++;return 0;
}

在這里插入圖片描述

2. 賦值運算符重載

賦值運算符重載是?個默認成員函數,?于完成兩個已經存在的對象直接的拷?賦值,這?要注意跟拷?構造區分,拷?構造?于?個對象拷?初始化給另?個要創建的對象。

賦值運算符重載的特點:

  1. 賦值運算符重載是?個運算符重載,規定必須重載為成員函數。賦值運算重載的參數建議寫成const當前類類型引?,否則會傳值傳參會有拷?。
  2. 有返回值,且建議寫成當前類類型引?,引?返回可以提?效率,有返回值?的是為了?持連續賦值場景。
  3. 沒有顯式實現時,編譯器會?動?成?個默認賦值運算符重載,默認賦值運算符重載?為跟默認拷貝構造函數類似,對內置類型成員變量會完成值拷?/淺拷?(?個字節?個字節的拷?),對?定義類型成員變量會調?他的賦值重載。
  4. 像Date這樣的類成員變量全是內置類型且沒有指向什么資源,編譯器?動?成的賦值運算符重載就可以完成需要的拷?,所以不需要我們顯?實現賦值運算符重載。像Stack這樣的類,雖然也都是內置類型,但是_a指向了資源,編譯器?動?成的賦值運算符重載完成的值拷?/淺拷?不符合我們的需求,所以需要我們??實現深拷?(對指向的資源也進?拷?)。像MyQueue這樣的類型內部主要是?定義類型Stack成員,編譯器?動?成的賦值運算符重載會調?Stack的賦值運算符重載,也不需要我們顯?實現MyQueue的賦值運算符重載。這?還有?個?技巧,如果?個類顯?實現了析構并釋放資源,那么他就需要顯?寫賦值運算符重載,否則就不需要。
#include <iostream>
using namespace std;class Date
{
public://無參構造函數Date(){_year = 2000;_month = 6;_day = 1;}//帶參構造函數Date(int year, int month, int day){_year = year;_month = month;_day = day;}//拷貝構造Date(Date& d){_year = d._year;_month = d._month;_day = d._day;}//賦值運算符重載Date& operator=(Date& d){// 不要檢查自己給自己賦值的情況if (this != &d){_year = d._year;_month = d._month;_day = d._day;} // d1 = d2表達式的返回對象應該為d1,也就是 * thisreturn *this;}void print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:int _year;int _month;int _day;
};int main()
{// 賦值重載完成兩個已經存在的對象直接的拷?賦值// 拷?構造用于一個對象拷?初始化給另一個要創建的對象Date d1(2024, 7, 14);//拷貝構造Date d2(d1);//拷貝構造Date d3 = d2;Date d4(2025, 5, 5);//賦值重載d3 = d4;d3.print();return 0;
}

在這里插入圖片描述

六、取地址運算符重載

const成員函數

將const修飾的成員函數稱之為const成員函數,const修飾成員函數放到成員函數參數列表的后?。

const實際修飾該成員函數隱含的this指針,表明在該成員函數中不能對類的任何成員進?修改。
const 修飾Date類的Print成員函數,Print隱含的this指針由 Date* const this 變為 const Date* const this

#include<iostream>
using namespace std;
class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;} // void Print(const Date* const this) constvoid Print() const{cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:int _year;int _month;int _day;
};int main()
{// 這里非const對象也可以調用const成員函數是?種權限的縮小Date d1(2024, 7, 14);d1.Print();const Date d2(2024, 8, 1);d2.Print();return 0;
}

在這里插入圖片描述

取地址運算符重載

取地址運算符重載分為普通取地址運算符重載const取地址運算符重載,?般這兩個函數編譯器?動?成的就可以夠我們?了,不需要去顯?實現。
除??些很特殊的場景,?如我們不想讓別?取到當前類對象的地址,就可以??實現?份,胡亂返回?個地址。

#include <iostream>
using namespace std;class Date
{
public :Date(){_year = 2024;_month = 7;_day = 14;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}Date* operator&(){//return this;//return nullptr;return (Date* )0x1256EF7;}const Date* operator&()const{//return this;//return nullptr;return (Date*)0x1256EA9;}
private:int _year;int _month;int _day;
};int main()
{Date d1;cout << &d1 << endl;const Date d2(2024, 8, 1);cout << &d2 << endl;return 0;
}

在這里插入圖片描述

七、應用:?期類實現

Date.h

#pragma once#include <iostream>
using namespace std;//日期類
class Date
{
public:Date(int year = 2000, int month = 1, int day = 1);//拷貝構造Date(const Date& d);//賦值運算符重載構造Date& operator=(const Date& d);~Date(){_year = 0;_month = 0;_day = 0;}void print() const;bool CheckDate() const;static int GetMonthDay(int year,int month){int arr[13] = { 0,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 arr[month] + 1;}return arr[month];}Date operator+(int day) const;Date& operator+=(int day);Date operator-(int day) const;Date& operator-=(int day);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;//++d 前置++Date& operator++();//d++ 后置++Date operator++(int);//日期相減  d1 - d2int operator-(const Date& d) const;friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);//取地址運算符重載Date* operator&(){//return this;//return nullptr;return (Date*)0x11451EF6;}const Date* operator&() const{//return this;//return nullptr;return (Date*)0x1145EE6;}private:int _year;int _month;int _day;
};ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);

Date.cpp

#include "Date.h"Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;if (!CheckDate()){cout << "日期錯誤:";print();}
}//拷貝構造
Date::Date(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;
}//賦值運算符重載構造
Date& Date::operator=(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;return *this;
}void Date::print() const
{cout << _year << " " << _month << " " << _day << endl;
}bool Date::CheckDate() const
{if (_month < 1 || _month > 12 || _day <= 0 || _day > GetMonthDay(_year, _month)){return false;}return true;
}Date Date::operator+(int day) const
{Date tmp = *this;tmp.operator+=(day);return tmp;
}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){_month = 1;_year++;}}return *this;
}Date Date::operator-(int day) const
{Date tmp = *this;tmp.operator-=(day);return tmp;
}
Date& Date::operator-=(int day)
{if (day < 0){return *this += (-day);}_day -= day;while (_day <= 0){_month--;if (_month == 0){_month = 12;_year--;}_day += GetMonthDay(_year, _month);}return *this;
}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 *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 _year == d._year && _month == d._month && _day == d._day;
}bool Date::operator!=(const Date& d) const
{return !(*this == d);
}//++d 前置++
Date& Date::operator++()
{return *this += 1;
}//d++ 后置++
Date Date::operator++(int)
{Date tmp = *this;*this += 1;return tmp;
}int Date::operator-(const Date& d) const
{int flag = 1;int n = 0;Date max = *this;Date min = d;if (*this < d){max = d;min = *this;}while (min != max){n++;min++;flag = -1;}return n * flag;
}ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}istream& operator>>(istream& in, Date& d)
{while (1){cout << "輸入年 月 日" << endl;in >> d._year >> d._month >> d._day;if (!d.CheckDate()){cout << "日期錯誤:";d.print();}else{break;}}return in;
}

test.cpp

#include "Date.h"void test01()
{Date d1;Date d2(2024, 7, 12);d1.print();d2.print();d2 += 30000;d2.print();Date d3 = d1 + 10000;d3.print();
}void test02()
{Date d1;Date d2(2024, 7, 13);d1.print();d2.print();d2 -= 30000;d2.print();//d2 = d1 - 100;//d2.print();
}void test03()
{Date d1(2024, 7, 13);Date d2(2024, 7, 19);cout << (d1 < d2) << endl;cout << (d1 <= d2) << endl;cout << (d1 > d2) << endl;cout << (d1 >= d2) << endl;cout << (d1 == d2) << endl;cout << (d1 != d2) << endl;
}void test04()
{Date d1(2024, 7, 13);Date d2(2024, 7, 13);Date tmp1 = d1++;tmp1.print();d1.print();Date tmp2 = ++d2;tmp2.print();d2.print();
}void test05()
{Date d1(2024, 7, 13);Date d2(2000, 7, 20);cout << d1 - d2 << endl;Date d3(2024, 6, 31);
}void test06()
{Date d1(2024, 7, 13);Date d2(2000, 7, 20);cout << d1 << d2 << endl;cin >> d1 >> d2;cout << d1 << d2 << endl;}void test07()
{Date d1(2024, 7, 13);Date d2(d1);d2.print();Date d3 = d1;d3.print();Date d4(2024, 6, 5);Date d5(2012, 3, 14);d4 = d5;d4.print();
}void test08()
{Date d1(2024, 7, 13);const Date d2(2000, 8, 19);cout << &d1 << endl;cout << &d2 << endl;
}void test09()
{Date d1;Date d2(2024, 7, 14);cout << (d2 += (-500)) << endl;cout << (d1 -= (-500)) << endl;
}int main()
{//test02();//test01();//test03();//test04();//test05();//test06();//test07();//test08();test09();return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/45711.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45711.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45711.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

技術成神之路:設計模式(七)狀態模式

1.介紹 狀態模式&#xff08;State Pattern&#xff09;是一種行為設計模式&#xff0c;它允許一個對象在其內部狀態改變時改變其行為。這個模式將狀態的相關行為封裝在獨立的狀態類中&#xff0c;并將不同狀態之間的轉換邏輯分離開來。 2.主要作用 狀態模式的主要作用是讓一個…

數據結構—鏈式二叉樹-C語言

代碼位置&#xff1a;test-c-2024: 對C語言習題代碼的練習 (gitee.com) 一、前言&#xff1a; 在現實中搜索二叉樹為常用的二叉樹之一&#xff0c;今天我們就要通過鏈表來實現搜索二叉樹。實現的操作有&#xff1a;建二叉樹、前序遍歷、中序遍歷、后序遍歷、求樹的節點個數、求…

SMU Summer 2024 Contest Round 4

SMU Summer 2024 Contest Round 4 2024.7.16 9:00————11:00 過題數3/7 補題數6/7 Made Up H and V Moving Piece Sum of Divisors Red and Green Apples Rem of Sum is Num Keep Connect A - Made Up 題解&#xff1a; 給定三個數組a&#xff0c;b&#xff0c;c&#xf…

MySQL日期和時間相關函數

目錄 1. 獲取當前時間和日期 2. 獲取當前日期 3. 獲取當前時間 4. 獲取單獨的年/月/日/時/分/秒 5. 添加時間間隔 date_add ( ) 6. 格式化日期 date_format ( ) 7. 字符串轉日期 str_to_date () 8. 第幾天 dayofxx 9. 當月最后一天 last_day ( ) 10. 日期差 datedif…

H. Beppa and SwerChat【雙指針】

思路分析&#xff1a;運用雙指針從后往前掃一遍&#xff0c;兩次分別記作數組a&#xff0c;b&#xff0c;分別使用雙指針i和j來掃&#xff0c;如果一樣就往前&#xff0c;如果不一樣&#xff0c;i–,ans #include<iostream> #include<cstring> #include<string…

SQL server 練習題2

課后作業 作業 1&#xff1a;自己查找方法&#xff0c;將 homework_1.xls 文件數據導入到 SQLServer 的 homework 數據庫中。數據導入完成后&#xff0c;把表名統一改為&#xff1a;外賣表 如下所示&#xff1a; 作業 2&#xff1a;找出所有在 2020 年 5 月 1 日至 5 月 31 …

Zookeeper之CAP理論及分布式一致性算法

CAP理論 CAP理論告訴我們&#xff0c;一個分布式系統不可能同時滿足以下三種 一致性&#xff08;C:consistency&#xff09;可用性&#xff08;A:Available&#xff09;分區容錯性&#xff08;P:Partition Tolerance&#xff09; 這三個基本要求&#xff0c;最多只能同時滿足…

python 語法學習 day2

python有七大數據類型, 數據類型轉換, 多變量賦值與print間隔, split函數, int用法總結python有七大數據類型&#xff1a; &#xff08;1&#xff09;數字&#xff08;Number&#xff09;&#xff1a;int(整型&#xff0c;長整型)&#xff0c;float(浮點型)&#xff0c;com…

部署k8s 1.28.9版本

繼上篇通過vagrant與virtualBox實現虛擬機的安裝。筆者已經將原有的vmware版本的虛擬機卸載掉了。這個場景下&#xff0c;需要重新安裝k8s 相關組件。由于之前寫的一篇文章本身也沒有截圖。只有命令。所以趁著現在。寫一篇&#xff0c;完整版帶截圖的步驟。現在行業這么卷。離…

SpringBoot中常用的注解及其用法

1. 常用類注解 RestController和Controller是Spring中用于定義控制器的兩個類注解. 1.1 RestController RestController是一個組合類注解,是Controller和ResponseBody兩個注解的組合,在使 用 RestController 注解標記的類中&#xff0c;每個方法的返回值都會以 JSON 或 XML…

【Android安全】Ubuntu 下載、編譯 、刷入Android-8.1.0_r1

0. 環境準備 Ubuntu 16.04 LTS&#xff08;預留至少95GB磁盤空間&#xff0c;實測占94.2GB&#xff09; Pixel 2 XL 要買歐版的&#xff0c;不要美版的。 歐版能解鎖BootLoader、能刷機。 美版IMEI里一般帶“v”或者"version"&#xff0c;這樣不能解鎖BootLoader、…

網絡安全-網絡安全及其防護措施2

6.安全設計和日志 安全審計 安全審計是對系統和網絡活動進行檢查和記錄的過程&#xff0c;確保合規性和安全性。審計過程可以幫助發現潛在的安全漏洞和違規行為&#xff0c;并驗證系統配置和操作的正確性。 定期審計 定義&#xff1a;定期檢查系統和網絡的安全配置和活動記錄…

394. 字符串解碼 739. 每日溫度(LeetCode熱題100)

394. 字符串解碼 - 力扣&#xff08;LeetCode&#xff09; curr_str&#xff1a;遍歷整個字符串時 如果左邊有[&#xff0c;且無相應右括號和其匹配&#xff0c;那么curr_str就表示該[到當前位置的解碼字符串如果左邊的[]已經匹配&#xff0c;或者沒有[]&#xff0c;curr_siz…

找不到vcruntime140_1.dll 無法執行的相關解決方法,如何高效率修復vcruntime140_1.dll

當出現“找不到 vcruntime140_1.dll 無法執行”這類提示時&#xff0c;意味著你的系統中的 vcruntime140_1.dll 文件已經缺失或者損壞。為了恢復并正常啟動你的程序&#xff0c;你需要對這個 DLL 文件進行修復。接下來&#xff0c;我們將詳細介紹如何進行這一操作。 一.找不到v…

數學建模·層次分析法

層次分析法 LAF 定義 評價體系的優劣影響&#xff0c;計算評價指標的權重的一種方法 主觀性較強&#xff0c;現在一般不用 主要步驟 關鍵在于一致性檢驗和求權值 權重的計算 注意權重之和為1&#xff0c;需要歸一化 算數平均法 特征值法 矩陣的一致性檢驗 為什么要檢驗…

【C語言】原碼、反碼、補碼詳解 -《碼上有道 ! 》

目錄 原碼、反碼、補碼詳解及其在C語言中的應用一、原碼&#xff08;Sign-Magnitude&#xff09;1.1 定義與表示1.2 歷史來源與作用1.3 示例1.4 C語言示例1.5 代碼運行結果 二、反碼&#xff08;Ones Complement&#xff09;2.1 定義與表示2.2 歷史來源與作用2.3 示例2.4 C語言…

sentinel網關限流配置及使用

sentinel控制臺源碼&#xff1a;https://download.csdn.net/download/yixin605691235/89543923 sentinel控制臺jar包&#xff1a;https://download.csdn.net/download/yixin605691235/89543931 不同環境直接修改jar包中的application.yml文件中的nacos地址就可以了。 一、網關限…

【LeetCode 0169】【摩爾投票算法】主元素

Majority Element Given an array nums of size n, return the majority element. The majority element is the element that appears more than ?n / 2? times. You may assume that the majority element always exists in the array. Example 1: **Input:** nums [3…

大數據信用查詢有哪些問題值得注意呢?

隨著大數據技術的不斷發展&#xff0c;大數據信用報告成為一種新型的信用風險檢測工具&#xff0c;被很多的銀行和機構廣泛用于信用風險評估&#xff0c;那大數據信用查詢有哪些問題值得注意呢?本文就帶大家一起去了解一下&#xff0c;希望對你有一定的幫助。 大數據信用查詢這…

JsonCPP源碼分析——分配器和配置器

1、allocator.h文件 該文件定義了一個分配器模版&#xff0c;該文件主要使用了內存對齊控制、rebind機制(C 標準庫的分配器接口要求提供 rebind 機制&#xff0c;以支持不同類型的分配)、::operator new、std::addressof等技術。 內存對齊控制&#xff1a;之所以先保存當前內存…