《C++ Premier》太难啃了,暂时先看郑秋生的《C/C++程序设计教程》应付考试。
C++是一门面向对象的程序语言,关于面向对象和面向过程,以前看过一篇文章,http://goo.gl/9eD4n,感觉讲解的非常好。
第一章类和对象
- 面向对象的基本特征
- 类是一种复杂的数据类型,将不同类型的数据,与这些数据相关的操作封装在一起。类是对现实
class { //数据成员和成员函数实现; }obj1, obj2, obj3;//只能定义一次。
客观世界的抽象,对象是类的一个实体。类具有属性和行为两方面要素。 - 封装是指将对象的数据与这个数据相关的操作放在一起,形成一个实体——对象。
- 继承(inheritance)机制可以使某个类(派生类、子类)继承另一个类(父类、基类)的特征和能力,加上自己特有的属性和行为,实现软件重用。
- 消息是一个对象向另一个对象发出的服务请求,进行对象之间的通信。
- 多态性(polymorphism)指同一个消息可以根据发送消息对象的不同而采取不同的行为方式。C++中的多态性包括静态多态和动态多态。静态多态在编译时能决定调用哪个函数,如函数重载,根据参数的不同,执行不同的操作;动态多态是由继承产生的,相关的但不同的类对象对同一消息会做出不同的响应,多是在程序运行时才能确定操作的对象,常用虚函数(virtual)来实现动态多态性。
- 类和对象
- 类是对象的抽象概括,对象是类的具体实现,由类创建具体的对象。类和对象的定义:
class 类名 { public: //公有,提供与外界的接口。公有成员可以被类作用域内的其他函数使用。 //数据成员和成员函数实现; protected: //保护,类的成员和继承类可以访问,类以外的函数不能访问。 //数据成员和成员函数实现; private: //私有,封装在类内部,只能被该类的成员、该类的友元函数和友元类访问。 //数据成员和成员函数实现; };
- 数据成员、成员函数、静态成员,数据成员就是对象中的数据部分,成员函数就是数据操作部分。
- 类对象的定义:
class myclass { //数据成员和成员函数实现; }; [class] myclass obj1, obj2, obj3;//class 可以省略
class myclass { //数据成员和成员函数实现; }obj1, obj2, obj3;
class { //数据成员和成员函数实现; }obj1, obj2, obj3;//只能定义一次
- 同一个类,不同对象的数据成员是不同的,成员函数是相同的。C++用同一内存空间来存放同种类对象的成员函数代码,用this指针指明哪个对象的成员函数。
- 类的成员函数
- 内联(inline)函数指类内定义的成员函数。函数的声明一般在头文件中,而头文件需要多次编译,所以定义不能放在头文件中。内联函数可以放在头文件中(头文件外用inline关键词)。内联函数规模小,调用频繁,调用时直接将函数代码嵌入到程序的调用点。
- 在类外定义成员函数,类的声明,类的定义。作用域运算符::
void Myclass::Myfunction();
- 对象成员引用
- 通过对象名和成员运算符访问对象中的成员
Myclass.Myobj; Myobj.Myfunction();
- 通过指向对象的指针和指针运算符访问对象中的成员
Myclass Myobj, *p; p=&Myobj;; p->Myfunction();
- 通过对象的引用变量访问对象中的成员
Myclass Myobj; Myclass &p=Myobj; //引用变量p p.Myfunction();
- 构造函数和析构函数
- 构造函数在创建对象时初始化数据成员,构析函数在对象生存周期结束时释放该对象。
- 构造函数
class Myclass { public: //应该是public属性 Myclass() { //与对象同名 cout<<"调用无参数的构造函数"<<endl; //一个对象在生存周期内只能调用一次 } }Myobj;
class Myclass { public: Myclass(int a, int b=0) { //构析函数可以根据参数定义多个,可以重载构造函数 cout<<"调用有参数的构造函数"<<endl; //构造函数可以带默认参数 } }Myobj;
- 当主函数运行到结束的花括号时,对象的生存空间结束,析构函数被调用。析构函数的调用顺序与构造函数相反。
- 析构函数
class::~Myclass() { //析构 }
- 拷贝函数,默认拷贝构造函数。拷贝函数是特殊的构造函数,用一个已知的对象初始化另一个对象。函数名与类名相同,没有返回值,只有一个参数,参数为该类对象的引用。定义格式:
三种情况下,需要拷贝函数初始化构造函数Myclass::Myclass(Myclass &d); //形参是一个对象的引用 Myclass::Myclass(const Myclass &d); //形参是一个const对象的引用
用一个对象创建另一个对象时,如果用户没有自己定义拷贝构造函数,编译系统会自动提供一个默认的拷贝构造函数。默认的拷贝构造函数将一个对象的全部数据成员赋值给另一个对象的数据成员。当类的数据成员中包括动态分配的资源时(char *p),会出现浅拷贝的问题(原对象obj1和拷贝后的对象obj2共用p的对空间,当删除p时,出现错误),这是必须自己定义拷贝函数。Myclass obj1(obj2);//用一个对象初始化另一个对象 function(Myclass obj1); //函数声明,函数的形参是一个类对象 return obj1; //对象作为函数的返回值,创建一个临时对象
- 类和对象的进一步应用
- C++中,动态分配堆空间是使用new和delete分配堆对象时自动调用构造函数和析构函数,用malloc和free不会自动调用,所以尽量使用new和delete。
- 组合类中用抽象的数据类型作为数据成员。
- 常对象只能访问常成员函数,常对象中的所有成员数据都不允许改变,只有常成员函数才能访问这些数据。
Myclass const obj(); const Myclass obj();
- 常数据成员与一般常变量相似,其数值不能改变。常数据成员只能通过构造函数的参数初始化列表对常数据成员进行初始化,不能采用赋初值的方法。
const int v; Myclass::Myclass(int a):v(a){...}; Myclass::Myclass(int a){v=a;};//错误
- 常成员函数
常成员函数只能访问本类中的数据成员(const和非const),不能修改值。只有常成员函数才能操作常量和常对象。int fuction() const;
- 静态成员
- 声明为static的类成员能够在类的范围中共享,称为数据成员。
- 静态数据成员
静态数据成员为类中所有成员共享,只占一份内存;静态数据成员是静态存储的,是静态生存期,在程序开始运行时分配内存,程序结束时释放内存。static int name; //定义 int Myclass::name=0; //初始化 Myclass::name //静态数据成员不属于任何一个对象,可以直接访问。
- 静态成员函数
静态成员函数可以直接访问静态数据和静态成员函数,不能直接访问非静态数据和非静态成员函数,可以通过对象来引用。static int function(); //定义 Myclass::function(); //直接访问
- 友元函数和友元类
- 类具有封装和数据隐藏的特性,只有类中的成员函数才可以访问protected和private成员。将类外的声明为friend后,可以访问。友元提高了程序的运行效率,但破坏了类的封装和隐藏性。
- 友元函数
友元函数是类外定义的一个函数,不是类的成员函数。friend int function(); //普通友元函数的声明 friend int Myclass::function1();//其他类的友元函数声明为该类的友元函数
- 友元类
A中的所有成员函数又是B的友元函数,可以访问B的private成员。友元关系不具有交换性和传递性。class B { ..... friend class A; //声明A为B的友元类 }
- string类
- char型字符串
动态分配字符串,其长度在运行时确定。Myclass::function(char *s) { len=strlen(s); con=new char[len+1]; strcpy(con,s); }
- string型字符串
string类有很多强大的成员函数。Myclass::fuction(string s) { con=s; }