C++学习笔记-类1
2013-03-20 15:35
204 查看
1.类作用域和类定义作用域
类定义作用域为包含类定义的花括号语句块,如果没有花括号语句块,则为从类定义开始的全部代码空间。
类作用域仅包括类定义内部和所有其成员函数的定义体。
上述代码中的成员函数f1访问了类定义中稍后声明的私有数据m(第16行)和成员函数f2(第14行),这是f1的权利。即使在类定义的外部,其成员函数f2(第18~23行)也可以访问私有数据m,只是敌不过函数体中的局部同名数据m,而遭到隐藏的冷遇,但通过类名空间的::操作,一样可以访问。
2.静态成员
静态数据成员:每个类只有一个静态数据成员实体,每个对象不再有它的副本。
整个类中只有一份number拷贝,所有的对象都共享这份拷贝。因此,输出学生总数时,访问的是唯一的静态数据成员,它不会因对象而异了。
定义静态成员的格式不能重复static关键字(第18行),但必须在成员名前冠以类名加域操作符,以表示该成员的类属。如果不将其初始化,则系统将为该成员清0。
3.静态成员函数
将静态成员做成私有的,用静态成员函数去访问静态数据成员是合适的。
静态成员函数并不受对象的牵制,可以用对象名调用静态成员函数,也可以用类名加上域操作符调用静态成员函数,这时候,将它看作是某个名空间的一个函数。
静态成员函数的实现位置与成员函数的实现位置应该是一起的,静态成员函数如果不在类中实现,而在类的外部实现时,类名前应免去static关键字。成员函数的静态性只在类中声明的时候才是必要的。
因为静态成员函数可以不以捆绑对象的形式调用,静态成员函数被调用时,没有当前对象的信息,所以静态成员函数不能访问数据成员,如下:
则编译通不过,error: illegal reference to non-static member 'Student::name。这并不是说它没有访问私有数据访问的权限,如果在静态成员函数中,给它传递一个Student对象:
那么,访问私有数据便是它的权利。
4.关于增量操作符的重载
一个整型变量的前增量操作的结果与变量值是一致的,而且前增量操作的结果是左值,操作可以连贯。而后增量操作的结果是增量之前的变量值,它是临时变量,当表达式计算工作完成后,该临时变量随即消失,所以变量最终值与后增量结果是错位的。例如:
在反映对象的前增量操作时,要求参数为对象的引用,返回的仍然是该对象参数的引用:
后增量操作符的重载,同样要求参数为对象的引用,因为在调用的上下文中,实参将发生变化,而返回则为临时对象,所以为非引用的对象值。在区分前后增量操作符时,C++做了一个技术处理:
调用后增量操作符的参数匹配是违背函数参数匹配常规的,编译专门做了特殊处理。
类定义作用域为包含类定义的花括号语句块,如果没有花括号语句块,则为从类定义开始的全部代码空间。
类作用域仅包括类定义内部和所有其成员函数的定义体。
#include <iostream> using namespace std; class X{ public: void f1(){ m = 6; f2(); } void f2(); private: int m; }; void X::f2() { cout<<"Data member: "<<m<<endl; // X::m int m = 7; cout<<"Local member: "<<m<<endl; //X::m被隐藏 cout<<"Data member: "<<X::m<<endl; } int main() //此处以下不属于类作用域但属于类定义作用域 { X x; x.f1(); }
上述代码中的成员函数f1访问了类定义中稍后声明的私有数据m(第16行)和成员函数f2(第14行),这是f1的权利。即使在类定义的外部,其成员函数f2(第18~23行)也可以访问私有数据m,只是敌不过函数体中的局部同名数据m,而遭到隐藏的冷遇,但通过类名空间的::操作,一样可以访问。
2.静态成员
静态数据成员:每个类只有一个静态数据成员实体,每个对象不再有它的副本。
#include <iostream> #include <string> //由于cout不支持string类型的数据,所以头文件中应该包括string using namespace std; class Student{ static int number; string name; public: Student(string str){ name = str; number++; } void print() { cout<<name<<"->students are "<<number<<" numbers\n"; } }; int Student::number = 0; //静态数据成员在类外分配空间和初始化 void fn() { Student s1("Smith"); Student s2("Randy"); s1.print(); } int main() { Student s("Smith"); fn(); s.print(); };
整个类中只有一份number拷贝,所有的对象都共享这份拷贝。因此,输出学生总数时,访问的是唯一的静态数据成员,它不会因对象而异了。
定义静态成员的格式不能重复static关键字(第18行),但必须在成员名前冠以类名加域操作符,以表示该成员的类属。如果不将其初始化,则系统将为该成员清0。
3.静态成员函数
将静态成员做成私有的,用静态成员函数去访问静态数据成员是合适的。
#include <iostream> #include <string> //由于cout不支持string类型的数据,所以头文件中应该包括string using namespace std; class Student{ static int number; string name; public: Student(string str){ name = str; number++; } static void printNumber(){ cout<<number<<" total numbers\n"; } void print() { cout<<name<<"->students are "<<number<<" numbers\n"; } }; int Student::number = 0; //静态数据成员在类外分配空间和初始化 void fn() { Student s1("Smith"); Student s2("Randy"); s1.print(); s1.printNumber(); } int main() { Student s("Jenny"); fn(); s.print(); Student::printNumber(); };
静态成员函数并不受对象的牵制,可以用对象名调用静态成员函数,也可以用类名加上域操作符调用静态成员函数,这时候,将它看作是某个名空间的一个函数。
静态成员函数的实现位置与成员函数的实现位置应该是一起的,静态成员函数如果不在类中实现,而在类的外部实现时,类名前应免去static关键字。成员函数的静态性只在类中声明的时候才是必要的。
因为静态成员函数可以不以捆绑对象的形式调用,静态成员函数被调用时,没有当前对象的信息,所以静态成员函数不能访问数据成员,如下:
static void printNumber(){ cout<<name<<number<<" total numbers\n"; }
则编译通不过,error: illegal reference to non-static member 'Student::name。这并不是说它没有访问私有数据访问的权限,如果在静态成员函数中,给它传递一个Student对象:
static void printNumber(Student& s){ cout<<"My name is "<<s.name<<"\n"; cout<<s.number<<" total number\n"; }
那么,访问私有数据便是它的权利。
4.关于增量操作符的重载
一个整型变量的前增量操作的结果与变量值是一致的,而且前增量操作的结果是左值,操作可以连贯。而后增量操作的结果是增量之前的变量值,它是临时变量,当表达式计算工作完成后,该临时变量随即消失,所以变量最终值与后增量结果是错位的。例如:
int a=1, b=1, c=1, d=1; (++a)++; //结果a=3 (b++)++; //结果b=2,(b++)的结果是临时变量,在其上加1随后又抛弃 ++(++c); //结果c=3 ++(d++); //结果d=2,与b相似
在反映对象的前增量操作时,要求参数为对象的引用,返回的仍然是该对象参数的引用:
X& operator++(X& a); //前增量操作符 ++a; //等价于operator++(a); 匹配上述操作符声明
后增量操作符的重载,同样要求参数为对象的引用,因为在调用的上下文中,实参将发生变化,而返回则为临时对象,所以为非引用的对象值。在区分前后增量操作符时,C++做了一个技术处理:
X operator++(X& a, int b); //后增量操作符 a++; //等价于operator++(a,1); 匹配上述操作符声明
调用后增量操作符的参数匹配是违背函数参数匹配常规的,编译专门做了特殊处理。
#include <iostream> #include <iomanip> using namespace std; class Time { int hour, minute, second; public: Time (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)%24; return a; } 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)%24; 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<<"\n"<<setfill(' '); } int main() { Time t(11, 59, 58); cout<<t++; cout<<++t; }
相关文章推荐
- c++学习笔记5,多重继承中派生类的构造函数与析构函数的调用顺序(二)
- C++学习笔记(七) 模板与泛型编程
- C++字符串处理函数学习笔记
- C++模版的详细介绍(学习笔记)
- C++ 学习笔记(18)异常处理(noexcept说明符和noexcept运算符、构造函数的try和catch)、命名空间(using声明和using指示)、多继承(虚继承)
- Inside the C++ Object Model 学习笔记 第四章 函数语意学
- C++学习笔记之类的构造函数
- C++学习笔记50——继承中的析构函数
- C++学习笔记 6th —— 结构体
- C++学习笔记(十二)虚继承
- C++学习笔记(第六章 指针的应用 字符串 引用 之二)
- C++ 函数模板和排序的函数模板——学习笔记
- OpenCV(C++接口)学习笔记1-图像的读取、显示、保存
- C++学习笔记:继承
- 【C++ 学习笔记小程序03】 整型及其相关知识
- C++学习笔记(一)--Sales_item类
- C++学习笔记(八) 智能指针
- C++学习笔记(五) 从C到C++
- C++学习笔记——VS2015程序的简单调试
- C++学习笔记-00