C++学习随笔8 面向对象编程(1)- 类
类
- 类定义
1 #include <iostream> 2 #include <iomanip> 3 using namespace std; 4 5 class Date{ 6 int year, month, day; 7 public: 8 //成员函数定义(在类的内部) 9 bool isLeapYear(){ 10 return (year%4==0 && year%100 != 0) || (year%400==0); 11 } 12 void set(int y, int m, int d) {year = y; month = m; day = d;} 13 //成员函数声明,定义在类的外部 14 void print(); 15 }; //定义类,必须加分号 16 17 //成员函数定义,必须加类型名和命名空间引导符:: 18 void Date::print(){ 19 cout<<setfill('0'); 20 cout<<setw(4)<<year<<'-'<<setw(2)<<month<<'-'<<setw(2)<<day<<'\n'; 21 cout<<setfill(' '); 22 } 23 24 int main(){ 25 Date d; //创建对象 26 d.set(2000, 12, 6); 27 if(d.isLeapYear()) 28 d.print(); 29 }
注意:只要是在类定义中包含的函数,就有默认声明内敛的性质,也就说该函数处于被编译自动安排到最佳运行性能的状态。因此,为了获取最佳性能,就应该在类编程时尽量把函数写入类定义中,使之称为成员函数。但编译是否真的将成员函数安排为内敛,还要看函数是否足够简单,是否包含不适于内敛运行的循环结构。所以,应尽量将成员函数的定义写到类定义的外部。
常成员函数:该成员函数不会改变对象值,在常成员函数中,任何改变对象值的操作,都将被编译器毫不留情地认定为错误。
常成员函数的声明和定义在形式上必须一致,即在函数形参列表的右括号后面加上const。
1 class Date{ 2 int year, month, day; 3 public: 4 void set(int y, int m, int d); 5 bool isLeapYear()const; 6 void print()const; 7 }; 8 9 //显示内敛 10 inline void Date::set(int y, int m, int d) {year = y; month = m; day = d;} //会改变对象至所以无法声明和定义成常成员函数 11 inline bool Date::isLeapYear() const{ 12 return (year%4==0 && year%100 != 0) || (year%400==0); 13 } 14 inline void Date::print() const{ 15 cout<<setfill('0'); 16 cout<<setw(4)<<year<<'-'<<setw(2)<<month<<'-'<<setw(2)<<day<<'\n'; 17 cout<<setfill(' '); 18 }
重载成员函数:成员函数与普通函数一样,可以重载。
- 操作符
操作符重载:
1 #include <iostream> 2 using namespace std; 3 4 class Point{ 5 int x, y; 6 public: 7 void set(int a, int b){x=a; y=b;} 8 void print()const{cout<<"("<<x<<", "<<y<<")\n";} 9 friend Point operator+(const Point &a, const Point &b);//作为外部函数要访问类的私有数据,必须加friend;若变为成员操作符即Point operator+(const Point &b); 10 }; 11 12 Point operator+(const Point &a, const Point &b) 13 { 14 Point s; 15 s.set(a.x + b.x, a.y + b.y); 16 return s; 17 } 18 19 int main(){ 20 Point a, b; 21 a.set(3, 2); 22 b.set(1, 5); 23 (a+b).print(); 24 operator+(a, b).print(); //a+b会被C++转译为operator+(a, b) 25 }
性质:
1.不能创建新的操作符
2.个别操作符不能重载("::"、"."、"? :"、sizeof、typeof)
3.优先级和结合性不变,重载操作符后,其优先级和结合性不变。
4.操作数个数不变,原先的操作符是单目的,重载也是单目形式的。
5.专门处理对象,即至少有一个参数是自定义类型。
6.忌意义相左,操作符重载后的新意义应该反应操作的本质。
增量操作符重载:
X& operator++(X &a); //前增量操作符,返回对象的引用
++a; //等价于operator++(a);
X operator++(X &a, int n); //后增量操作符,返回对象
a++; //等价于operator++(a, 1);
成员操作符:
成员操作符声明和定义中省略了第一个参数,因为成员函数总是与对象捆绑使用的,被捆绑的对象就是被操作的第一个参数。因此,单目成员操作符没有参数,双目成员操作符只有一个参数。
s+t == s.operator+(t)
类的程序架构:
类的定义放在头文件中;类的实现放在一个单独的.cpp文件中;类的应用放在别的.cpp文件中。
- 静态数据成员
静态数据成员在类外分配空间和初始化,应省略static。
class Student{ class Student{ static int number = 0; == static int number; ... ... }; }; int Student::number = 0;
//静态数据成员在类内初始化不能放在头文件中,通常应将其放在类的实现代码中。
- 静态成员函数
通常应该将静态数据成员设为私有的,用静态成员函数去访问静态数据成员。
静态成员函数如果不在类中实现,而在类的外部实现时,类名前应该免去static关键字。成员函数的静态性只在类中声明的时候才是必要的。
注意:
因为静态成员函数可以不捆绑对象的形式调用,静态成员函数被调用时,没有当前对象的信息,所以静态成员函数不能访问非静态数据成员。
- 友元(friend)
private成员只能被本类成员函数、友元函数或友元类的成员函数访问,不能被派生类访问,该类对象也不能访问;
protected成员可以被该类中函数,子类中的函数,其友元函数访问,但不能被该类对象访问;
public成员可以被任意访问,该类对象也可以访问;
1.普通函数声明为类的友元,就可以直接访问类的私有数据;
2.友元还经常用在操作符重载中,例如:friend ostream& operator<<(ostream& o, const Point& d); cout<<d;
3.成员函数可以是另一个类的友元:例如,教师应该可以修改学生的成绩,可以访问学生类的私有数据,故将教师类中的assignGrade成员函数声明为学生类的友元;
1 class Student;//因为Teacher类中有Student的声明,Student中有Teacher类的声明,而类型名使用之前必须声明,所以这里在Teacher类定义之前,先声明Student类,称为前向声明 2 class Teacher{ 3 Student * pList; 4 public: 5 //... 6 //注意,首先我们声明Student,是为了在Teacher类中assignGrade方法可以使用其引用类型的形参,而该方法的定义需要放到Student类定义之后,因为此时才知道Student类型有哪些成员。 7 void assignGrade(Student &s); 8 }; 9 10 class Student{ 11 Teacher* pT; 12 int semesterHours; 13 double grade; 14 public: 15 //... 16 friend void Teacher::assignGrade(Student &s); 17 }; 18 19 void Teacher::assignGrade(Student &s) 20 { 21 s.grade = 100; 22 }
4.整个类也可以是友元,此时称该类友元为友类。友类的每个成员函数都可以访问另一个类中的私有成员。例如,将整个教师类看作是学生类的友类,教师既可以修改成绩,又可以调整学时数:
1 class Student; 2 class Teacher{ 3 Student* pList; 4 public: 5 void assignGrade(Student &s); 6 void adjustHours(Student &s); 7 }; 8 9 class Student{ 10 Teacher* pT; 11 int semesterHours; 12 double grade; 13 public: 14 //... 15 friend class Teacher; 16 };

浙公网安备 33010602011771号