1.特征:抽象,封装--静态特征、行为特征,继承,多态
2.c++多的:函数重载,引用,带默认值的参数,string,新的数据类型bool
3.给函数参数指定默认值,缺省参数,并且必须从右往左赋值,参数传递有顺序
4.函数重载:函数名相同,参数表不同(个数/类型)----只有这个是区分条件,注意返回值类型不是区分的特征
5.修改引用的值也就修改了原始变量的值,但是修改原始变量不会改变引用的值,定义引用的同时必须赋值
6.static int cnt;//不能在类中初始化
静态数据成员在类的外面初始化,因为他属于整个类,在类中初始化就每创建一个对象就都初始化为零 int Date::cnt=0;
访问类的静态成员:用对象或者类。可用类直接调用:cout<<Date::getCnt()<<endl;
static作用域不变,生存周期变长,一直用的是第一次初始化的值
// //static修饰文件,这个函数只能在这个文件里用;否则可以在所有项目中使用
// //static修饰函数,这个函数只能在这个文件里用
// //static静态成员变量,属于类成员,不属于某个对象
7.定义和声明区别是是否开辟空间
//inline void Date::setDay(int d){day=d;}//使他成为内联函数
内联函数inline:综合宏和函数的优点,抛弃缺点,在编译阶段运行
// //macro宏 #define(预处理命令)---可以带参数(变量)
// //宏定义 宏调用 宏替换--编译之前把定义的东西都替换了,不会有流的转移
// //宏的执行速度比函数快,但是没有语法检查
// //类的里面定义的函数都是内联函数
// //在类外面定义成员函数
8.Date date,date2(2025,4,23);//初始化写法
//生成对象的顺序按照定义对象的顺序
9.Date date3=date2,date4(date3);//对象赋值对象的写法
10.析构函数:只有一个,不能重载。无参数。无返回值类型。析构函数调用顺序与构造函数调用顺序相反,因为后面的构造函数用前面的构造函数的空间
11.写程序的时候最好写一个不带参的默认构造函数(给缺省值也可以)
12.const bool sex;//常数据成员不能在默认构造函数体中初始化
13.fee=new double[age];//圆括号赋初值,中括号开空间
14.如何赋值指针数组
Person(string a,bool b,int c,double f[]):sex(false)
{
name=a;
// sex=b;
age=c;
fee=new double[age];
//fee=f;错误,这样是赋值地址,fee没得到f中所有的值
for(int i=0;i<age;i++)
fee[i]=f[i];
cout<<"A Person "<<name<<" is Created"<<endl;
}
15.指针的浅拷贝与深拷贝
Person(const Person& another):sex(another.sex)//去掉引用会复制一份给形参,调用拷贝构造
{
name=another.name;
// sex=another.sex;
age=another.age;
// fee=another.fee;//浅拷贝,都指向一个内存单元,一个改另一个改,一个变另一个也变,不可取
//法一:深拷贝,可取
fee=new double[another.age];
for(int i=0;i<another.age;i++)
fee[i]=another.fee[i];
//法二:深拷贝----可取
double *tmp;
tmp=new double[age];
for(int i=0;i<age;i++)
tmp[i]=another.fee[i];
fee=new double[age];
for(int i=0;i<age;i++)
fee[i]=tmp[i];
delete []tmp;
cout<<"A Person "<<name<<" is cloned"<<endl;
}
16.再往里面传一个数就要重新开辟空间
void increase(double f)//age++就要多申请空间啊,怎么弄呢?
{//c中realloc可以在原来的基础上继续申请空间,但c++不支持
age++;
//中间过渡作用
double *tmp=new double[age];
for(int i=0;i<age;i++)
tmp[i]=fee[i];
delete []fee;//把原来的释放掉,再申请新空间
fee=new double[age];
for(int i=0;i<age-1;i++)
fee[i]=tmp[i];
fee[age-1]=f;
delete []tmp;
}
17.及时释放空间
~Person()
{
delete []fee;//fee是数组,要加中括号,构造函数中有new申请空间时在这里要释放掉,很重要!!!!!!!!!!!!!!!!!
cout<<"A Person "<<name<<" is areased"<<endl;
}
18.常成员函数由const修饰符修饰,表明在常成员函数中不得修改类中的任何数据成员的值;常成员函数可以修改传入自身的形参以及内部定义的局部变量
19.
// const int *p;//指针常量,指向常量的指针,不能通过指针来改变指针指向的值
// int const *p;//常量指针,与上行意义相同
// const (int*) p;//常量指针,与上行意义相同
// const int * const p;//指向常量的常量指针,指针变量本身是常量,不能改变(即不能让它指向另一个值
// const int const *p;//与 const int *p;一样,因为const要么修饰指针,要么修饰变量。这里两个const都在*前面,相当于只有一个
/const int *pa=&a;//通过指针来改指针指向的值不行,可以直接改a,报错assignment read-only
//int const *pa=&a;//与上一行意义一样,指针常量
//int *const pa=&a;//pa=&b错,表示指针变量本身是常量,不能改变,只能指向a,常量指针
const int *const pa=&a;//指向常量指针的指针常量
//int *pa[10];下标运算优先级最高(其次是*),是数组,有十个指针,每个指针指向int,指针数组
//int (*pa)[10];指针,指向数组,数组有十个值,每个值都是int,数组指针
//int * f();函数,函数返回值是指针,指针指向int型变量,指针函数
//int * f(int*);函数参数是指向整型变量的指针,返回值是指向整型变量的指针,指针函数
//int(*f)();f是指向返回值为int的函数的指针,指针函数
//int*(*f)();f是指向返回值为int指针的函数的指针,函数指针
20.
普通对象可以调用常成员函数,即所有对象都可以调用常成员函数
常对象只能调用常成员函数,常对象数据成员值不能改
21.
Person *pPerson;//只这样定义指针不会调用构造函数
22.
区分重载:参数个数 参数类型 是否为常函数
一个常成员函数和普通成员函数可以构成重载
23.
什么时候调用拷贝构造
一定调用:用一个对象初始化另一个对象时,对象作为形参进行形参传递时
返回值是类的对象时不一定会调用
24.
组合类中类的对象成员(拷贝构造函数)在初始化列表中初始化,常成员函数(属于某个对象)也在这初始化//父类的成员必须成员初始化列表这初始化------常数据成员、父类、组合对象
引用在定义的时候初始化
构造函数可以由系统自动调用,也可以手动调用
构造函数调用顺序:先调用父类的构造函数,再调用组合对象的构造函数(按照对象成员的定义顺序),再组合类的构造函数 (先调用父类的组合的构造函数,再调用父类的构造函数,之后调用子类的组合的构造函数,最后调用子类自身的构造函数;)
析构函数调用顺序与之相反
静态数据成员在类外初始化,所有对象共有的,普通成员函数可以直接访问类中的静态数据成员,静态成员函数(属于整个类,无this指针,指向当前对象)只能访问静态数据成员不能访问普通数据成员
inline在调用过程中不调用栈,内存少
类内部定义的函数默认是内联函数
数组名是指向首元素的地址,相当于指针
int a[],int *a,int &a;可以将被调函数的整型参数值a带回主调函数(这三个都代表取地址)
区分同名函数是否为重载函数:参数类型;参数个数;是否为常函数;//一个常成员函数和普通成员函数可以构成重载
//继承顺序决定构造函数调用顺序(先person,后base),析构函数相反
25.访问控制权限
//证明访问权限
#include <iostream>
// 基类
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
// 公有继承
class PublicChild : public Base {
public:
void accessMembers() {
publicMember = 1; // 正常访问
protectedMember = 2; // 正常访问
// privateMember = 3; // 错误:不能从外部访问
}
};
// 私有继承
class PrivateChild : private Base {
public:
void accessMembers() {
publicMember = 1; // 正常访问
protectedMember = 2; // 正常访问
// privateMember = 3; // 错误:不能从外部访问
}
};
// 保护继承
class ProtectedChild : protected Base {
public:
void accessMembers() {
publicMember = 1; // 正常访问
protectedMember = 2; // 正常访问
// privateMember = 3; // 错误:不能从外部访问
}
};
int main() {
PublicChild publicChild;
// publicChild.privateMember; // 错误:不能从外部访问
PrivateChild privateChild;
// privateChild.privateMember; // 错误:不能从外部访问
ProtectedChild protectedChild;
// protectedChild.privateMember; // 错误:不能从外部访问
return 0;
}
父类的public可以在main函数中用,main函数中定义了子类的对象
子类中能访问public和protected
孙子类是公有继承,那么子类中的继承关系不变,来验证子类继承父类后父类的变量在子类中变成了什么访问控制权限
从main函数出发,main函数中比较直接
#include <iostream>
using namespace std;
class Base
{
public:
Base(int a,int b,int c)
{
pubData=a;
proData=b;
priData=c;
}
int pubData;
protected:
int proData;
private:
int priData;
};
class Son:public Base
{
public:
Son(int a,int b,int c):Base(a,b,c)
{
}
};
class GrandSon:public Son
{//父类是带参的构造函数,那子类就一定要弄带参的构造函数,父类决定子类
public://子类初始化调用父类构造函数,子类初始化父类一定跟着初始化,因为子类继承父类
GrandSon(int a,int b,int c):Son(a,b,c)
{
}
void f()//重写
{
proData=10;//在子类中可以访问,那就是protected
}
};
int main()
{
Son son(10,20,0);
cout<<son.pubData<<endl;
// cout<<son.proData<<endl;//在这不能输出,一定不是protected
}
26.
子类初始化调用父类构造函数
27.
类模板生成模板类,模板类生成对象
类模板不能直接定义对象,生成模板类之后才能定义对象
模板类。模板类创建出来的两个实例a b
Data<int> a(10),b(20),c;相当于在对象后面加个模板,模板中有想让它成为的数据类型
<关键字 类型参数>
//template <typename T>
类模板不能当父类
28.
//运算符重载
//让自定义的类可以使用运算符
①一般情况下,单目运算符最好重载为类的成员函数,双目运算符则最好重载为类的友元函数;
②双目运算符“=、()、[]、->”不能重载为类的友元函数。输入输出运算符必须重载为友元函数
若要返回在重载运算符函数内新定义的对象,则必须拷贝值返回,不能引用返回。同时,由于值返回,返回的是一个临时变量,他是具有常属性的 需要用const引用进行接收的(参数需要加const)
//=为赋值运算符,eg拷贝有指针的时候要深拷贝,有指针成员要写赋值运算符的深拷贝,系统自动生成的是浅拷贝
例:
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
class Date
{
private:
int year,month,day;
public:
Date(int y=0,int m=0,int d=0)
{
year=y;
month=m;
day=d;
}
void show() const
{
cout<<year<<"-"<<month<<"-"<<day<<endl;
}
int operator-(const Date& another)
{
Date d;
d.day=day-another.day;
d.month=month-another.month;
d.year=year-another.year;
int m;
m=d.day+d.month*30+d.year*12*30;
return m>=0?m:-m;
}
Date operator+(const int i)
{
day+=i;
if(day>30)
{
month++;
day-=30;
}
if(month>12)
{
month-=12;
year++;
}
return *this;
}
bool operator>(const Date& another)
{
// if(year>another.year)
// return true;
// else if(year==another.year&&month>another.month)
// return true;
// else if(year==another.year&&month==another.month&&day>another.day)
// return true;
// else
// return false;
// return 直接返回
if(year!=another.year)
return year>another.year;
if(month!=another.month)
return month>another.month;
if(day!=another.day)
return day>another.day;
return false;
//法三
//比较距离0年0月0日的天数
}
void setDate(int y,int m,int d)
{
year=y;month=m;day=d;
}
Date operator++()
{
day+=1;
if(day>30)
{
month++;
day-=30;
}
if(month>12)
{
month-=12;
year++;
}
return *this;
}
Date operator++(int)//虚参数--后缀
{
Date tmp(*this);
day+=1;
if(day>30)
{
month++;
day-=30;
}
if(month>12)
{
month-=12;
year++;
}
return tmp;
}
bool operator==(const Date& another)
{
bool flag;
flag=year==another.year;
flag=flag&&(month==another.month);
flag=flag&&(day==another.day);
}
//无需返回值类型:构造析构强制类型转换函数
operator int()
{
return year*360+month*30+day;
}
//无this指针,友元不受控制权限影响
friend istream& operator>>(istream& is,Date& date);
friend ostream& operator<<(ostream& os,const Date& date);
};
istream& operator>>(istream& is,Date& date)
{
is>>date.year>>date.month>>date.day;
return is;
}
ostream& operator<<(ostream& os,const Date& date)
{
os<<date.year<<"-"<<date.month<<"-"<<date.day<<endl;
}
class DateList
{
private:
vector<Date> dates;
vector<Date>::iterator it;
int n;
public:
void SetDates()
{
int y,m,d;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>y>>m>>d;
Date tmp(y,m,d);
dates.push_back(tmp);
}
}
void ShowDates()
{
for(it=dates.begin();it!=dates.end();it++)
{
it->show();
}
}
void Sort()
{
Date tmp;
for(int j=0; j<n; j++)
{
for(int k=0; k<n-j-1; k++)
{
if(dates[k]>dates[k+1])
{
tmp=dates[k];
dates[k]=dates[k+1];
dates[k+1]=tmp;
}
}
}
}
vector<int> operator-(const DateList& another)
{
vector<int> cha;
for(int i=0;i<n;i++)
{
cha.push_back(dates[i]-another.dates[i]);
}
return cha;
}
// vector<Date> operator+(int str[])
// {
// vector<Date> he;
// for(int i=0;i<dates.size();i++)
// {
// he.push_back(dates[i]+str[i]);
// }
// return he;
// }
DateList operator+(vector<int> v)
{
DateList _dates;
for(int i=0;i<dates.size()&&i<v.size();i++)
{
_dates.dates.push_back(dates[i]+v[i]);
}
int i;
while(i<dates.size())
{
_dates.dates.push_back(dates[i]);
}
return _dates;
}
bool operator>(const DateList& another)
{
for(int i=0;i<n;i++)
{
if(dates[i]>another.dates[i])
;
else
return false;
}
return true;//返回谁的下标没达到最大值
}
Date operator[](int index)
{
return dates[index];
}
int operator[](Date& date)
{
vector<Date>::iterator it;
for(it=dates.begin();it<dates.end();it++)
{
if(*it==date)
return it-dates.begin();//得到下标值
}
}
};
int main()
{
// Date d1(2021,3,10),d2(2021,3,11);
// int n=d1-d2;
// bool m=d1>d2;
// cout<<m<<endl;
// cout<<n<<endl;
//STL排序
// freopen("ini.txt","r",stdin);
// Date dates[10];//没给初值={Date(2020,1,1)}----手工调用构造函数
// int i,y,m,d;
// //给Date赋值的方法
// //定义成员函数
// //构造一个对象,用拷贝构造
// for(i=0;i<10;i++)
// {
// cin>>y>>m>>d;
// dates[i].setDate(y,m,d);
// }
// //冒泡排序
// for(int j=0;j<10;j++)
// {
// for(int k=0;k<10-j-1;k++)
// {
// if(dates[k]>dates[k+1])
// {
// Date tmp=dates[k];
// dates[k]=dates[k+1];
// dates[k+1]=tmp;
// }
// }
// }
// for(i=0;i<10;i++)
// {
// dates[i].show();
// }
// freopen("ini.txt","r",stdin);
// int i,y,m,d;
// vector<Date> dates;
// int n;
// cin>>n;
// for(int i=0;i<n;i++)
// {
// cin>>y>>m>>d;
// Date tmp(y,m,d);
// dates.push_back(tmp);
// }
vector<Date>::iterator it1;
vector<Date>::iterator it2;
for(it1=dates.begin();it1!=dates.end();it1++)
{
for(it2=dates.begin();it2!=dates.end();it2++)
{
if((*it2)>(*(it2)+1))
{
Date* tmp=it2;
it2=it2+1;
it2+1=tmp;
}
}
}
//
// vector<Date>::iterator it;
// for(it=dates.begin();it!=dates.end();it++)
// {
// it->show();
// }
// vector<Date>::iterator it1;
// vector<Date>::iterator it2;
// for(it1=dates.begin();it1!=dates.end();it1++)
// {
// for(it2=dates.begin();it2!=dates.end();it2++)
// {
// if((*it2)>(*(it2+1))
// {
// Date* tmp=it2;
// it2=it2+1;
// it2+1=tmp;
// }
// }
// }
// freopen("ini.txt","r",stdin);
// DateList dl;
// DateList lis;
// lis.SetDates();
// lis.Sort();
// lis.ShowDates();
// freopen("ini.txt","r",stdin);
// DateList lis,lis2;
// lis.SetDates();
// lis.Sort();
// lis2.SetDates();
// lis2.Sort();
// vector<int> n;
// n=lis-lis2;
// for(int i=0;i<n.size();i++)
// {
// cout<<n[i]<<" ";
// }
// DateList lis1;
// DateList lis2;
// lis1.SetDates();
// lis1.Sort();
// lis1.ShowDates();
// lis2.SetDates();
// lis2.Sort();
// lis2.ShowDates();
// vector<int> a;
// a=lis1-lis2;
// vector<Date> b;
// int arr[10];
// for(int i=0;i<10;i++)
// {
// cin>>arr[i];
// }
// b=lis1+arr;
// bool dx=lis1>lis2;
// cout<<dx<<endl;
// cout<<endl;
// for(int i=0;i<a.size();i++)
// {
// cout<<a[i]<<endl;
// }
// cout<<endl;
// for(int i=0;i<b.size();i++)
// {
// b[i].show();
// }
//Date date(2020,1,1),d;
//d=date++;
//d.show();
//date.show();
//d=++date;
//d.show();
//date.show();
// Date date;
// cin>>date;
// // date.show();
// cout<<date;
// // date.show();
// DateList lis,lis2,lis3;
// lis.SetDates();
// cout<<lis[0]<<endl;
// Date t(2000,1,1);
// cout<<lis[t]<<endl;
//强制类型转换
Date t(2000,1,1);
cout<<(int)t<<endl;
return 0;
}