c++学习第七天
创作过程中难免有不足,若您发现本文内容有误,恳请不吝赐教。
提示:以下是本篇文章正文内容,下面案例可供参考。
一、const成员函数
//Date.h
#pragma once
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1);
//两个Print()可以同时存在,构成函数重载
void Print() const;
void Print();
private:
int _year;
int _month;
int _day;
};
//Date.cpp
#include"Date.h"
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
// 检查日期是否合法
if (month < 1 || month > 12
|| day < 1 || day > GetMonthDay(year, month))
{
cout << "非法日期" << endl;
// exit(-1);
}
}
//void Date::Print(const Date* this)
void Date::Print() const
{
cout << _year << "年" << _month << "月" << _day << "日" << endl;
}
//void Date::Print(Date* this)
void Date::Print()
{
cout << _year << "年" << _month << "月" << endl;
}
//Test.cpp
#include"Date.h"
int main()
{
const Date d1(2025, 1, 1);
d1.Print();
Date d2(2025, 1, 2);
d2.Print();
}
//Date.h
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) const;
Date& operator-=(int day);
Date operator-(int day) const;
Date& operator++();
Date operator++(int);
Date& operator--();
Date operator--(int);
int operator-(const Date& d) const;
简单来说:只读函数可以加const,内部不涉及修改成员的都是只读函数
二、取地址及const取地址操作符重载
//Test.cpp
#include"Date.h"
int main()
{
const Date d1(2025, 1, 2);
d1.Print();
cout << &d1 << endl;
Date d2(2025, 1, 7);
d2.Print();
cout << &d2 << endl;
return 0;
}
理论上上面的代码是不能运行的,因为自定义类型使用运算符需要重载。因为取地址及const取地址操作符重载这两个默认成员函数一般不用重新定义 ,编译器默认会生成。
//自己写如下:
//日常使用自动生成的就可以了
Date* operator&()
{
return this;
}
const Date* operator&() const
{
return this;
}
// 不想被取到有效地址才自己写
Date* operator&()
{
return nullptr;
}
const Date* operator&() const
{
return this;
}
三、流插入和流提取
//Date.h
void operator<<(ostream& out);
//Date.cpp
void Date::operator<<(ostream& out)
{
out << _year << "/" << _month << "/" << _day << endl;
}
//Test.cpp
#include"Date.h"
int main()
{
Date d1(2025, 1, 21);
cout << d1 ;
return 0;
}
原因:参数顺序不匹配
//Test.cpp
#include"Date.h"
int main()
{
Date d1(2025, 1, 21);
d1 << cout ;
return 0;
}
不能写成成员函数,因为成员函数this指针永远占据第一个,所以只能往全局上写。
//Date.h
#pragma once
#include<iostream>
using namespace std;
class Date
{
// 友元声明
//因为operator<<写在函数外面不能访问到_year,_month,_day
friend void operator<<(ostream& out, const Date& d);
Date(int year = 1, int month = 1, int day = 1);
public:
void Print();
private:
int _year;
int _month;
int _day;
};
void operator<<(ostream& out, const Date& d);
//Date.cpp
#include"Date.h"
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
// 检查日期是否合法
if (month < 1 || month > 12
|| day < 1 || day > GetMonthDay(year, month))
{
cout << "非法日期" << endl;
// exit(-1);
}
}
void Date::Print()
{
cout << _year << "年" << _month << "月" << endl;
}
void operator<<(ostream& out, const Date& d)
{
out << d._year << "/" << d._month << "/" << d._day << endl;
}
//Test.cpp
#include"Date.h"
int main()
{
Date d1(2025, 1, 21);
Date d2(2024, 2, 2);
cout << d1 ;
return 0;
}
//Test.cpp
#include"Date.h"
int main()
{
Date d1(2025, 1, 21);
Date d2(2024, 2, 2);
cout << d1 << d2 ;
return 0;
}
//Date.h
#pragma once
#include<iostream>
using namespace std;
class Date
{
friend ostream& operator<<(ostream& out, const Date& d);
Date(int year = 1, int month = 1, int day = 1);
public:
void Print();
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& out, const Date& d);
//Date.cpp
#include"Date.h"
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
// 检查日期是否合法
if (month < 1 || month > 12
|| day < 1 || day > GetMonthDay(year, month))
{
cout << "非法日期" << endl;
// exit(-1);
}
}
void Date::Print()
{
cout << _year << "年" << _month << "月" << endl;
}
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "/" << d._month << "/" << d._day << endl;
return out;
}
//Date.h
#pragma once
#include<iostream>
using namespace std;
class Date
{
// 友元声明
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);
Date(int year = 1, int month = 1, int day = 1);
public:
void Print();
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& out, const Date& d);
//这里不能加const,因为这是在内部修改让外部拿到这个值
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 (month < 1 || month > 12
|| day < 1 || day > GetMonthDay(year, month))
{
cout << "非法日期" << endl;
// exit(-1);
}
}
void Date::Print()
{
cout << _year << "年" << _month << "月" << endl;
}
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "/" << d._month << "/" << d._day << endl;
return out;
}
istream& operator>>(istream& in, Date& d)
{
in >> d._year >> d._month >> d._day;
return in;
}
//Test.cpp
#include"Date.h"
int main()
{
Date d1(2025, 1, 21);
Date d2(2024, 2, 2);
cout << d1 << d2;
cin >> d1;
cout << d1;
return 0;
}
四、再谈构造函数
1.初始化列表
class Date
{
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
class A
{
public:
A(int a = 0)
:_a(a)
{}
private:
int _a;
};
class Date
{
public:
// 初始化列表是每个成员定义的地方
// 不管你写不写,每个成员都要走初始化列表
Date(int year, int month, int day, int& i)
: _year(year)
, _month(month)
,_a(1)
,_refi(i)
{
// 赋值
_day = day;
}
private:
int _year; // 每个成员声明
int _month = 1 ;
int _day = 1;
// C++11支持给缺省值,这个缺省值给初始化列表
// 如果初始化列表没有显示给值,就用这个缺省值
// 如果显示给值了,就不用这个缺省值
//这里_day会使用缺省值,而_month不会使用
// 下面三个例子必须定义时初始化
const int _x = 10;
int& _refi;
A _a;
};
注意:
1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)。
2.类中包含以下成员,必须放在初始化列表位置进行初始化:
①引用成员变量 ②const成员变量 ③自定义类型成员(且该类没有默认构造函数时)
4.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后
总结:
能用初始化列表就用初始化初始化列表,但有些场景还是需要初始化列表和函数体混着用。
五、explicit关键字
#include<iostream>
using namespace std;
class A
{
public:
A(int i)
//A(int i)
:_a(i)
{
cout << "A(int i)" << endl;
}
private:
int _a;
};
int main()
{
A aa1(1);
// 单参数构造函数的隐式类型转换
// 用2调用A构造函数生成一个临时对象,再用这个对象去拷贝构造aa2
// 编译器会再优化,优化用2直接构造
A aa2 = 2;
return 0;
}
A& ref1 = 2;
这里的问题原因是临时对象具有常性,ref不能引用,属于权限的放大,加上const就没有问题了。
const A& ref1 = 2;
#include<iostream>
using namespace std;
class B
{
public:
B(int b1, int b2)
//explicit B(int b1, int b2)
:_b1(b1)
, _b2(b2)
{
cout << "B(int b1, int b2)" << endl;
}
private:
int _b1;
int _b2;
};
int main()
{
// C++11 支持多参数的隐式类型转换
B bb1(1, 1);
B bb2 = { 2, 2 };
const B& ref2 = { 3,3 };
return 0;
}
class B
{
public:
explicit B(int b1, int b2)
:_b1(b1)
, _b2(b2)
{
cout << "B(int b1, int b2)" << endl;
}
private:
int _b1;
int _b2;
};
重点:
class A
{
public:
explicit A(int i)
:_a(i)
{
cout << "A(int i)" << endl;
}
private:
int _a;
};
class B
{
public:
explicit B(int b1, int b2)
:_b1(b1)
, _b2(b2)
{
cout << "B(int b1, int b2)" << endl;
}
private:
int _b1;
int _b2;
};
六、生命周期
#include<iostream>
using namespace std;
class A
{
public:
explicit A(int i)
:_a(i)
{
cout << "A(int i)" << endl;
}
A(const A& aa)
:_a(aa._a)
{
cout << "A(const A& aa)" << endl;
}
~A()
{
cout << "~A()" << _a << endl;
}
private:
int _a;
};
int main()
{
// 有名对象 特点:生命周期在当前局部域
A aa6(6);
// 匿名对象。特点:生命周期只在这一行
A(7);
return 0;
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了c++的基础。
原文地址:https://blog.csdn.net/weixin_74239807/article/details/145256771
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!