[C++] 自定义的类如何使用“cout“和“cin“?(含日期类实现)

23 篇文章 0 订阅
订阅专栏

一、引言

在C++中,“cin”和"cout"可以说是区别于C语言的一大亮点。

但是,它的自动识别类型,其本质不过是运算符重载。若真到了能够“自动识别”的那一天,人类大概也能进入新的纪元了罢。

对于我们自己写的类,想要用cout,cin,当然是可以的,我们只需自己写它的重载即可。

本文将以“cout”为例。

二、运算符重载

1、何为运算符重载 

运算符重载:

函数名: operator操作符
返回类型: 看操作符运算后返回值是什么
参数:操作符有几个操作数,它就有几个参数 

其中,有5 个符号是不能进行运算符重载的:::      sizeof         ?:      .      .* 

2、日期类

下面我们以日期类为例,熟悉运算符重载:

众所周知,如果直接在类中进行运算符重载,那么第一个操作数必定是隐含的this指针。

这样就会产生一个问题:本应是“cout<<d”,如今却要写成“d<<cout”

void Test3()
{
	Date d1(2023, 8, 9);
	Date d2(2023, 12, 20);
	Date d3(2003, 12, 1);

	d1 << cout;
	d2 << cout;
	d3 << cout;
}

int main()
{
	Test3();

	return 0;
}

class Date
{
	friend void operator<< (ostream& out, const Date& d);

public:

	// 获取某年某月的天数
	int GetMonthDay(int year, int month)
	{
		int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
		{
			days[2] = 29;
		}
		return days[month];
	}

	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;

		if (month < 1 || month > 12 || day < 1 || day > GetMonthDay(year, month))
		{
			cout << "非法日期" << endl;
		}
	}

	// 拷贝构造函数
    // d2(d1)
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	// 赋值运算符重载
  // d2 = d3 -> d2.operator=(&d2, d3)
	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;

		return *this;
	}

	// 析构函数
	~Date()
	{
		;
	}

	//打印
	void Print() const
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}

	// 日期+=天数
	Date& operator+=(int day)
	{
		if (day < 0)
		{
			*this -= (-day);
			return *this;
		}
		_day += day;

		while (_day > GetMonthDay(_year, _month))
		{
			_day -= GetMonthDay(_year, _month);
			_month++;

			if (_month > 12)
			{
				_year++;
				_month = 1;
			}
		}

		return *this;
	}

	// 日期+天数
	Date operator+(int day)
	{
		Date tmp = *this;
		tmp += day;
		return tmp;
	}

	// 日期-天数
	Date operator-(int day)
	{
		Date tmp = *this;
		tmp -= day;
		return tmp;
	}

	// 日期-=天数
	Date& operator-=(int day)
	{
		if (day < 0)
		{
			*this += (-day);
			return *this;
		}
		_day -= day;

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

		}

		return *this;
	}

	// 前置++
	Date& operator++()
	{
		*this += 1;
		return *this;
	}

	// 后置++
	Date operator++(int)
	{
		Date tmp = *this;
		*this += 1;
		return tmp;
	}

	// 后置--
	Date operator--(int)
	{
		Date tmp = *this;
		*this -= 1;
		return tmp;
	}

	// 前置--
	Date& operator--()
	{
		*this -= 1;
		return *this;
	}

	// >运算符重载
	bool operator>(const Date& d)
	{
		if (_year > d._year)
		{
			return true;
		}
		else if(_year == d._year)
		{
			if (_month > d._month)
			{
				return true;
			}
			else if (_month == d._month)
			{
				if (_day > d._day)
				{
					return true;
				}
			}
		}

		return false;
	}

	// ==运算符重载
	bool operator==(const Date& d)
	{
		return _year == d._year && _month == d._month && _day == d._day;
	}

	// >=运算符重载
	bool operator >= (const Date& d)
	{
		return *this > d || *this == d;
	}

	// <运算符重载
	bool operator < (const Date& d)
	{
		return !(*this >= d);
	}

	// <=运算符重载
	bool operator <= (const Date& d)
	{
		return !(*this > d);
	}

	// !=运算符重载
	bool operator != (const Date& d)
	{
		return !(*this == d);
	}

	// 日期-日期 返回天数
	int operator-(const Date& d)
	{
		int num = 0;
		Date max = *this;
		Date min = d;
		int flag = 1;
		if (*this < d)
		{
			flag = -1;
			max = d;
			min = *this;
		}

		while (max > min)
		{
			num++;
			min++;
		}

		return flag * num;
	}

	void operator<< (ostream& cout) const
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}

private:

	int _year;
	int _month;
	int _day;

};

3、“cout<<d”

要想使得代码是“cout<<d”而非“d<<cout”,

其实也很简单。我们将<<的重载写在类的外面,就没有了“隐含的this指针”的限制。

但是这样又会产生一个问题:如何访问Date类的私有成员呢?

这时,我们可以利用“友元”来解决问题。

#include<iostream>
using namespace std;



class Date
{
//设置友元
	friend void operator<< (ostream& out, const Date& d);

public:

	// 获取某年某月的天数
	int GetMonthDay(int year, int month)
	{
		int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
		if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
		{
			days[2] = 29;
		}
		return days[month];
	}

	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;

		if (month < 1 || month > 12 || day < 1 || day > GetMonthDay(year, month))
		{
			cout << "非法日期" << endl;
		}
	}

	// 拷贝构造函数
    // d2(d1)
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}

	// 赋值运算符重载
  // d2 = d3 -> d2.operator=(&d2, d3)
	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;

		return *this;
	}

	// 析构函数
	~Date()
	{
		;
	}

	//打印
	void Print() const
	{
		cout << _year << "年" << _month << "月" << _day << "日" << endl;
	}

	// 日期+=天数
	Date& operator+=(int day)
	{
		if (day < 0)
		{
			*this -= (-day);
			return *this;
		}
		_day += day;

		while (_day > GetMonthDay(_year, _month))
		{
			_day -= GetMonthDay(_year, _month);
			_month++;

			if (_month > 12)
			{
				_year++;
				_month = 1;
			}
		}

		return *this;
	}

	// 日期+天数
	Date operator+(int day)
	{
		Date tmp = *this;
		tmp += day;
		return tmp;
	}

	// 日期-天数
	Date operator-(int day)
	{
		Date tmp = *this;
		tmp -= day;
		return tmp;
	}

	// 日期-=天数
	Date& operator-=(int day)
	{
		if (day < 0)
		{
			*this += (-day);
			return *this;
		}
		_day -= day;

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

		}

		return *this;
	}

	// 前置++
	Date& operator++()
	{
		*this += 1;
		return *this;
	}

	// 后置++
	Date operator++(int)
	{
		Date tmp = *this;
		*this += 1;
		return tmp;
	}

	// 后置--
	Date operator--(int)
	{
		Date tmp = *this;
		*this -= 1;
		return tmp;
	}

	// 前置--
	Date& operator--()
	{
		*this -= 1;
		return *this;
	}

	// >运算符重载
	bool operator>(const Date& d)
	{
		if (_year > d._year)
		{
			return true;
		}
		else if(_year == d._year)
		{
			if (_month > d._month)
			{
				return true;
			}
			else if (_month == d._month)
			{
				if (_day > d._day)
				{
					return true;
				}
			}
		}

		return false;
	}

	// ==运算符重载
	bool operator==(const Date& d)
	{
		return _year == d._year && _month == d._month && _day == d._day;
	}

	// >=运算符重载
	bool operator >= (const Date& d)
	{
		return *this > d || *this == d;
	}

	// <运算符重载
	bool operator < (const Date& d)
	{
		return !(*this >= d);
	}

	// <=运算符重载
	bool operator <= (const Date& d)
	{
		return !(*this > d);
	}

	// !=运算符重载
	bool operator != (const Date& d)
	{
		return !(*this == d);
	}

	// 日期-日期 返回天数
	int operator-(const Date& d)
	{
		int num = 0;
		Date max = *this;
		Date min = d;
		int flag = 1;
		if (*this < d)
		{
			flag = -1;
			max = d;
			min = *this;
		}

		while (max > min)
		{
			num++;
			min++;
		}

		return flag * num;
	}


private:

	int _year;
	int _month;
	int _day;

};

//运算符重载
void operator<< (ostream& cout, const Date& d)
{
	cout << d._year << "年" << d._month << "月" << d._day << "日" << endl;
}

效果 

void Test3()
{
	Date d1(2023, 8, 9);
	Date d2(2023, 12, 20);
	Date d3(2003, 12, 1);

	cout << d1;
	cout << d2;
	cout << d3;

}

int main()
{
	Test3();

	return 0;
}

如此,我们就实现了将自定义的类使用cout输出了。 

4、连续使用

如果我们需要连续使用,那么就需要对其进行修改。

ostream& operator<< (ostream& cout, const Date& d)
{
	cout << d._year << "年" << d._month << "月" << d._day << "日" << endl;

	return cout;
}
void Test3()
{
	Date d1(2023, 8, 9);
	Date d2(2023, 12, 20);
	Date d3(2003, 12, 1);

	cout << d1 << d2 << d3;

}

int main()
{
	Test3();

	return 0;
}

效果

 

C++:cout<<自定义型输出
我不是萧海哇的博客
11-25 1028
1.自定义型 struct Student{ int id; string name; Student(); Student(int ID,string Name){ id=ID; name=Name; } friend ostream & operator << (ostream &out,const Student &s) { out<<s.id&lt
C++自定义使用标准输入cin输出cout
最新发布
肩上风骋的博客
02-19 498
当自己定义的数据为一些复杂数据,不再为基本数据型,这时候要使用cout输出这些数据,就需要重载输出运算符
C++ 自己实现cout
Mount256的博客
08-04 2118
前排提示:阅读本篇文章需要至少学过和对象以及重载运算符的概念。 文章目录一、cout是谁?二、什么是namespace?三、自己实现cout 接触这么久C++了,我想尝试写一个自己的cout了。在实现之前,先扯扯几个概念: 一、cout是谁? 不就是输出语句嘛?!这个答案太浅显。正确答案:coutostream的一个对象,而这个对象有一个成员重载运算符函数:operator <<。顺便一说,ostream又属于iostream库中,iostream是标准的C++头文件。既然如此,那么这个
实现C++中的cout
不休的博客
08-20 1110
在学习C++时,一直很好奇cout输出时用 代码如下: out.h: #ifndef OUT_H #define OUT_H namespace mystd { class mycout { public: mycout operator (const char * str); }; extern mycou
C++ cout使用,看这一篇就够了
Jasmine-Lily的博客
04-25 4万+
1 C++输入输出综述 C++ IO首先建立在为Unix环境开发的原始库函数上;ANSI C正式承认这个库时,将其称为标准输入/输出包; IO相关定义在头文件iostream和fstream,这些不是正式语言定义的组成部分,cin,istream都不是关键字。 1.1 流和缓冲 (1)流简介: C++程序将输入和输出看作字符流;对于输入来说,程序从输入流中抽取字符,对于输出来说,程序向输出流中插入字符; 输入流可以来自键盘、存储设备或者其他程序;输出流可以输出至显示器、打印机、存储设备或者其他程序。
C++——和对象3|日期类型|Cout运算符重载|Cin运算符重载|const成员|
weixin_49449676的博客
08-31 1262
Date*型。
C++自定义string字符串
07-15
自定义`MyString`不仅能够帮助我们理解C++面向对象编程的基本概念,如封装、继承和多态,还能加深对C++内存管理和标准库中`std::string`的理解。通过实现这个,我们可以更好地掌握字符串处理的核心技巧,这...
C++-输入输出(cout&cin
qq_52916060的博客
12-12 547
在 C语言中,通常会采用格式化输入输出函数 printf() 和 scanf() 用于输入或输出数据或信息。在 C++语言中,C语言的这一套输入输出库我们仍能使用,但是 C++语言又自定义了一套新的、更容易使用的输入输出库。 在 C++程序中,输入与输出可以看做是一连串的数据流,输入即可视为从文件或键盘中输入程序中的一串数据流,而输出则可以视为从程序中输出一连串的数据流到显示屏或文件中。 在编写 C++程序时,如果需要使用输入输出时,则需要包头文件<iostream>。<iostream
c++中输入输出, cincout,ifstream ofstream getline等IO接口详解
weixin_44845956的博客
03-28 2083
c++中的输入输出都是用“”来进行,无论是 cin,和cout都是的一个对象。 c++中负责IO的有3中型 1: istream、ostream 从流读写数据(i表示in也就是读,o表示out也就是写),你可以认为流就是控制台输入输出的数据,cincout就分别是他们俩的对象。 2: ifstream、ofstream f 表示file,也就是从文件读写数据 3: istringstream, ostringstream 从string读写数据。 其中2,3是继承的1。那么有了这些之后读写过
C++ PPT第3章 和对象(一).ppt
05-30
面向对象编程是C++的核心特性,它通过和对象实现数据和操作的封装,从而提供更高级别的抽象和模块化。在C++中,(Class)是定义对象(Object)蓝图的蓝图,包了数据成员(Data Members)和成员函数(Member ...
c++程序】输入日期
平凡的世界
03-07 2243
#include using namespace std; struct Date { int year; int mon; int day; }; Date input() { Date d; cout<<"input the date (yyyy mm dd):"; cin>>d.year>>d.mon>>d.day; return d; } int main() { Da
C++中的 cout 和 printf 用法
攻城狮的博客
05-18 6149
C++是一种面向对象的编程语言,它继承了C语言的特点,同时也增加了许多新的特性。在C++中的cout 和 printf是两种常用的输出函数,它们都可以将数据显示在屏幕上,但是它们也有一些区别和优缺点。本文将详细说明这两种函数的区别及格式化输出的不同实现方法。
c++运算符重载简单讲解 cout输出自定义数据
AKGWSB 's blog
05-28 4531
目录表达式与运算符运算符及其重载本质(附代码)两种重载运算符函数的方式以成员函数的形式重载以友元函数的形式重载单目运算符的重载前++,即 ++a 的重载及(附代码)后++,即 a++ 的重载(附代码)双目运算符的重载(附代码)cout输出自定义型(附代码) 表达式与运算符 一个表达式由 结果,左值,运算符,右值 构成,当然有的表达式也可以没有结果,比如++(自增)运算 我们可以轻易的使用以下语句来完成int型变量的加法运算 int a = 114, b = 514; int c = a + b;
C++cout使用
热门推荐
九霄星河的博客
09-21 21万+
C++cout使用1. cout使用的三种方式2. cout和i/i++/++i的组合使用3. 以不同进制输出数字4. 输出数字位数的控制5. 强制显示小数点和正负号6. 设置宽度和对齐方式7. 设置填充字符8. iomanip库用法总结 coutC++中 ostream 型的对象,该被封装在 &amp;lt; iostream &amp;gt; 库中,该库定义的名字都在命名空间 std 中,所以 c...
C++初阶】和对象终极篇
每天都要坚持刷题的博客
11-04 717
学完了这一节,你将会使用cout
cin的输入方式
java领域博主
04-25 8447
cin常用的有三种方法: cin>> cin.get() cin.getline()
如何让自定义能像cout(ostream)那样输出数据
norman_irsa的博客
11-09 2167
相信不少C++程序员初次看到下面的写法时,一定留下了深刻印象: #include<iostream> using namespace std; int main() { cout << "Hello World!" << endl; } 至少,对于当时从C语言转向学习C++的我是深感震惊,如此形象直观的输出方式,简直是黑科技。 那么如何在自定义...
C++自定义复数的输入输出流实现详解
本资源是一份关于C++第10章输入输出流的详细教程,重点在于讲解如何在自定义的complex实现输入输出流的操作。C++的输入输出流功能是编程中不可或缺的一部分,它允许我们读取和写入数据到标准输入输出设备,如...
写文章

热门文章

  • 【C语言】中,输入一个数组,实现将输入的n个数字按照从大到小的顺序输出。【通俗简单易懂】 27301
  • [C语言]中,为什么整型数据以浮点型输出(或浮点数类型的数据以整型输出),其输出的结果与我们预期的大相径庭?这篇博客,带你拨开云雾见月明。 4068
  • [C语言] 冒泡排序法 - 详解 2797
  • [visual studio]中,关于如何 【调试】 的问题 及 技巧 2784
  • 【C++】常用到的“using namespace std;”到底是什么? 2515

分类专栏

  • C++ 23篇
  • 数据结构 18篇
  • Linux 9篇
  • C语言 26篇

最新评论

  • [C++] 自定义的类如何使用“cout“和“cin“?(含日期类实现)

    helloworldwjsr: 其实在class的private里可以用friend(友好成员函数)来重载,这样就能指定cout在前面了[code=cpp] friend void operator<< (ostream& cout, const Date& d) { cout << d._year << "年" << d._month << "月" << d._day << "日" << endl; } [/code]

  • 【C语言】中,输入一个数组,实现将输入的n个数字按照从大到小的顺序输出。【通俗简单易懂】

    杯酒问苍天: 因为动态开辟的话,n就可以随意输入,不用定死。 不过我没记错的话,C99就支持了变长数组,这种就不用动态开辟,直接写成int arr[n]。 但是这样老一点的版本就会报错

  • 【C语言】中,输入一个数组,实现将输入的n个数字按照从大到小的顺序输出。【通俗简单易懂】

    XiaoLllei: 作者大大,为什么要动态开辟数组嘞

  • 【C语言】中,输入一个数组,实现将输入的n个数字按照从大到小的顺序输出。【通俗简单易懂】

    XiaoLllei: 作者大大,为什么要动态开辟数组嘞

  • [linux]进程控制——进程等待

    CSDN-Ada助手: CS入门 技能树或许可以帮到你:https://edu.csdn.net/skill/gml?utm_source=AI_act_gml

最新文章

  • 博客系统测试报告
  • [C++] C++11新增
  • [C++]智能指针
2024年21篇
2023年38篇
2022年1篇

目录

目录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杯酒问苍天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家扬州人物玻璃钢雕塑加工澳门商场新年美陈周年庆典商场美陈供货商鞍山出口沈阳玻璃钢花盆怎么把泡沫雕塑变成玻璃钢模具云南玻璃钢雕塑的设计制作贵不贵江门人物玻璃钢雕塑苏州知名玻璃钢雕塑推荐货源铜陵玻璃钢长颈鹿雕塑哪里做玻璃钢雕塑的多关公玻璃钢雕塑定制吉林玻璃钢卡通雕塑厂家批发商场美陈场景堆箱四川公园玻璃钢雕塑制作榆林卡通玻璃钢雕塑生产厂家七台河人物玻璃钢雕塑安装绍兴玻璃钢花盆生产玻璃钢古代人物雕塑厂家电话玻璃钢雕塑制上海景观玻璃钢雕塑价格江苏商场主题创意商业美陈公司湖北标牌标识校园玻璃钢景观雕塑信阳附近不锈钢玻璃钢雕塑公司石家庄直销玻璃钢雕塑畅销全国桥北春节商场美陈荆门人物玻璃钢雕塑公司福建佛像玻璃钢雕塑定做价格商场美陈找客户佛山玻璃钢雕塑价格厂家中庭商场美陈售价香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化