类的产生:提供了一种可以重用代码的机制,使得程序员编程的代码可以相互利用
类实际上是一种新产生的数据类型,那就要求给数据类型命名,数据类型名称采用大写字母开头的命名方法。
类包括数据成员和成员函数,成员函数可以在类内部定义,也可以在类外部定义,如果采用在外部定义的话,就要在函数名称前面加上类名Date和名空间引导符"::"。
成员函数的定义:
成员函数一定从属于类,而不能独立存在,则也就是为什么在函数名前面加上类名的道理。
只要是在类定义中包含的成员函数,就有默认声明内联的性质
什么是内联函数呢?参考https://blog.csdn.net/cloud323/article/details/68065098
编译是否真的将成员函数安排为内联,还要看函数是否足够简单,是否包含不适于内联运行的循环结构。
日期类的实现:
#include <iostream> #include <iomanip> using namespace std; class Date { int year,month,day; public: void set(int y,int m,int d){ year = y,month = m,day = d; } bool isLeapyear(); void print(); }; inline bool Date::isLeapyear() { return (year%4==0&&year%100!=0||year%400==0); } void Date::print() { cout << setfill('0'); cout << setw(4)<< year << '-' << setw(2) << month << '-' << setw(2) << day << "\n"; cout << setfill(' '); }
还可以使用对象指针
Date* dp = new Date;
dp->set(2000,12,6);
if(dp->isLeapyear())
(*dp).print();
常成员函数:
成员函数的操作,如果只是对对象进行读操作,则该成员函数设计成常成员函数。
经验之谈:能够成为常成员函数的,应尽量写成常成员函数
void Date::print()const{} 这就是常成员函数的定义。
操作符重载:
#include <iostream> #include <iomanip> using namespace std; class Point { int x,y; public: void set(int a,int b):x(a),y(b){ } void print()const { cout << x << ", " << y << endl; } friend Point operator+ (const Point& a,const Point& b); friend Point add (const Point &a,const Point&b); }; Point operator+ (const Point& a,const Point& b) { Point s; s.set(a.x+b.x,a.y+b.y); return s; } Point add(const Point& a,const Point& b) { Point s; s.set(a.x+b.x,a.y+b.y); return s; }
任何自定义的+操作符的行为都是对c++原有+操作符的重载,其他操作符的定义也是重载行为。
因为operator+ 和 add函数体中都要用到Point对象进行私有数据访问,作为普通函数,这是不允许的,编译器也会报错,但是其在Point类中以friend关键字引导进行的函数声明后,编译就对这两个函数访问Point的私有数据网开一面了。
增量操作符的重载:
#include <iostream> #include <iomanip> using namespace std; class Time { int hour,minute,second; public: void set(int h,int m,int s) { hour = h,minute = m,second = s; } friend Time& operator++(Time& a); friend Time operator++ (Time& a,int); friend ostream& operator<< (ostream& o,const Time& t); }; //前增量++ Time& operator++(Time& a) { if(!(a.second=(a.second+1)%60)&&!(a.minute=(a.minute+1)%60)) a.hour = (a.hour+1)%60; return a; } //后增量++ ,为了和前增量区分,参数里面多加了一个int,用以区分 Time operator++ (Time& a,int) { Time t(a); if(!(a.second=(a.second+1)%60)&&!(a.minute=(a.minute+1)%60)) a.hour = (a.hour+1)%60; return t; } //重载<<运算符 ostream& operator <<(ostream& o,const Time& t) { o << setfill('0') << setw(2) <<t.hour << ":" << setw(2) << t.minute << ":"; return o << setw(2) << t.second << endl << setfill(' '); }
成员操作符:
成员操作符与普通操作符不同的是:成员操作符声明和定义中省略了第一个参数,因为成员函数总是和对象绑定使用的,被绑定的对象就是被操作的第一参数。因此单目成员操作符没有参数,双目成员操作符只有一个参数。
重载<< 操作符的时候,因为<<操作的前置对象是流类型的cout,不是point类型,所以不能把<<操作设计成Point的成员,而只能设计成普通的函数,而且为了能够访问Point的私有数据,必须用关键字friend引导。
静态数据成员:
有些属性不是类中每个对象分别拥有的,而是类所共有的,保证每个类只有一个实体,每个对象中不再有它的副本,国有的对象都共享这份实体。
静态成员函数:
可以使用对象名调用静态成员函数,也可以使用类名加上域操作符调用静态成员函数,如
Student s,
s.print() 或者 Student::print()
静态成员函数如果不在类中实现,而在类外实现时,类名前应免去static关键字,成员函数的静态性只在类中声明的时候才是必要的。
静态成员函数调用的时候,如果没有当前的对象信息,所以对象成员函数不能访问数据成员。
友元
将一个普通函数声明为类的友元,就可以直接访问类的私有数据。
友元函数的定义一般放在类的实现中,以作为类的不可分割的一部分。友元可以看作是类操作中的一种访问权限不到位的补充。