6.1
定义格式:
class 类名
{
public:
公有数据成员和成员函数;
protected:
保护数据成员和成员函数;
private:
私有数据成员和成员函数;}
注意事项:
1、类成员可以为其他类对象
2、不能以类自身的对象作为本类的成员
3、类自身的指针和引用可以作为类的成员
4、以“;”结束类的定义
| 类具有封装性,而结构体没有,因为结构体成员为 公有。
|类行为属性通过成员函数实现;
首先将成员函数声明为函数原型,在类外具体定义成 员函数。
|成员函数的定义模式为:
返回值类型 类名::成员函数名(参数表)
{
函数体
}
|对象与类关系即为基本数据类型和变量之间的关系,
先定义类再定义类的对象。
|可通过原点访问形式(对象名.公有成员)和指针访问形式(对象指针变量名->公有成员)进行类成员的访问。
|内联函数可减少频繁调用小子程序的运行时间开销;
其形式为:
inline 函数原型
注:内联函数仅在函数原型做一次声明;
适用于只有1-5行小函数;
不可含有复杂结构控制语句,不可递归调用
|函数重载即为函数名相同,而参数不相同(类型不同、个数不同)的函数;
其用于处理不同数据类型的类似任务。
|参数个数相同
类型不同:
int main() {cout<<abs(-5)<<endl; cout<<abs(-7.8)<<endl; } int abs(int a) {return a<0 ? -a:a;} double abs(double f) { return abs(double f) {return f<0 ? -f:f;}
|参数个数不同:
int main() { cout<<max(5,3)<<endl; cout<<max(4,8,2)<<endl; } int max(int a,int b) { return a>b?a:b; } int max(int a,int b,int c) { int t; { t=max(a,b); return max(t,c); }
6.2 构造函数与析构函数
|构造函数作用:
为对象分配空间;
对数据成员赋初值;
请求其他成员;
|构造函数名与类名相同;
|构造函数可以重载;
|构造函数无返回值,但有各种类型形参;
|析构函数用于取消对象的成员函数,进行对象消 亡时的清理工作;
|当无用户定义构造函数和析构函数时,系统提供 缺省版本的构造函数和析构函数,缺省的构造函数 为空函数;
|析构函数无参数也无返回类型;
|用构造函数创建对象时,通过指针和new来实现 :类名 *指针变量=new 类名(实参表);
Date *date1=Date(1998,4,28);
即创建了对象(*date1)
|构造函数初始化成员俩种方法:
1、使用构造函数的函数体进行初始化;
2、使用构造函数的初始化列表进行初始化;
例1:
class Date { int d, m, y; public: Date(int dd, int mm, int yy) { d=dd; m=mm; y=yy; } Date(int dd, int mm) { d=dd; m=mm; } }
例2:
class Date { int d, m, y; public: Date(int dd, int mm, int yy):d(dd),m (mm),y(yy) { } Date(int dd, int mm): d(dd),m(mm) { } }
|类的初始化顺序:
按照数据成员在类中的声明顺序进行初始化,
与初始化成员列表中的顺序无关。
|重载构造函数,构造函数可进行重载,系统将根据参数匹配其中一个。
class Box{ public: Box(); Box(int ,int , int); int volume(); private: int height,width, length; }; Box::Box() { height=10; width=10; length=10;} Box::Box(int h, int w,int l):height(h),width(w),length(l) {} int Box::volume() { return width*length*height;} int main(){ Box box1; cout<<"The volume is "<<box1.volume(); Box box2(12,30,25); cout<<"The volume is "<<box2.volume(); return 0; }
|this指针:
C++专门设立了一个名为this的指针,用来指向不同 的对象;
一个对象的this指针不是对象本身的一部分,不会 影响sizeof(对象)的结果;
以此可区分不同实例对象的数据成员;
|需要显示引用this指针的情况:
在类的非静态成员函数中返回类对象本身或 对象的引用的时候,直接使用 return *this,返回本 对象的地址时,return this;
当参数与成员变量名相同时,如this->x = x,不 能写成x = x;
避免对同一对象进行赋值操作,判断两个对象是 否相同时,使用this指针;
|复制构造函数:
分为深复制与浅复制;
|浅复制:
对于复杂类型的数据成员只复制了存储地址而没 有复制存储内容;
默认复制构造函数为浅复制;
#include <iostream> #include <string.h> using namespace std; class Person { public: Person(char* name1,int a,double s); void display(){cout<<name<<"\t"<<age<<"\t"<<salary<<endl;} ~Person(){delete name;} //析构函数的声明 private: char* name; int age; double salary; }; int main() { Person *P1=new Person("WangWei ",8,3880); //调用构造函数创建对象P1 P1->display(); Person P2(*P1); //调用复制构造函数,用P1的数据初始化对象P2 delete P1; P2.display(); return 0; } |深复制: 通过一个对象初始化另一个对象时,不仅复制了 数据成员,也复制了资源的复制方式为深复制。 |深复制构造函数的特点: 定义:类名::类名([const]类名 &对象名); Person::Person(const Person& P0) //复制构造函数的实现 { name=new char[strlen(P0.name)+1]; strcpy(name,P0.name); age=P0.age; salary=P0.salary; cout<<"ff"<<endl; }
6.3 类的其他成员:
|常成员(指数据成员在实例化被初始后,其值不能改变)
|静态成员
|友元
|常成员:
#include<iostream> using namespace std ; class Simple { int x, y ; public : void setXY ( int a, int b) { x = a ; y = b ; } void printXY() { cout << x << "," << y << endl ; } void constFun ( ) const { x ++ ; y ++ ; }//非法 };
|静态成员:
类成员冠以static声明时,为静态成员;
静态成员为同类对象共享;
静态成员函数与静态数据成员协同操作;
|静态成员函数的作用不是为了对象之间的沟通,而是为了
能处理静态数据成员,可以在不依赖某个对象的情况下,
访问静态成员。
class A { int n; static int s; }
|公有的静态成员的访问形式:
类名::静态成员的名字;
对象名.静态成员名字;
对象指针->静态成员名字;
静态成员函数内部直接访问;
|静态数据成员的声明及初始化:
类外声明
类型类名::静态数据成员【=初始化值】;
#include<iostream> using namespace std ; class counter { static int num ; public : void setnum ( int i ) { num = i ;} void shownum() { cout <<num << '\t' ; } } ; int counter :: num = 0 ; int main () { counter a , b ; a.shownum(); b.shownum() ; a.setnum(10) ; a.shownum() ; b.shownum() ; cout<<endl ; }
|静态成员函数仅可以访问静态成员函数或静态数据成员;
静态成员的引用不需要用对象名;
静态成员函数没有this指针;
|友元函数:
在类A以外的其他地方定义一个函数(函数B);
在类体中用friend对函数B声明,函数B即为函数A的友元函数,但A不是B的友元;
类B可以访问类A的私有数据成员;
当B为A的友元函数,则B的所有成员函数都为A的友元函数;
友元函数定义一定要按顺序,当B为A的友元函数,则必须先定义A再定义B;
样例:
class { private: int i ; friend void FriendFun(A * , int) ; //定义友元函数 public: void MemberFun(int) ; } ; … void FriendFun( A * ptr , int x ) { ptr -> i = x ; } ; void A:: MemberFun( int x ) { i = x ; } ;
6.4
|类的包含:
类的包含是程序设计中一种软件重用技术,
即定义一个类时,通过编译器把另一个“类”抄进来;
|建立一个类的对象时,要先执行成员对象自己的构 造函数,再执行当前类的构造函数;
|成员对象的构造函数调用次序和成员对象在类中的 说明次序一致(声明顺序为:a1、b1、b2),与它 们在成员初始化列表中出现的次序无关(初始化 列表顺序为 :b1、b2、a1);
析构函数的调用顺序相反;
#include<iostream> using namespace std; class A { public: A(int x):a(x){ } int a ; }; class B { public: B( int x, int y ) : aa(x) { b = y ; } void out() { cout<<"aa = "<<aa.a<<endl<<"b = "<<b<<endl ; } private: int b ; A aa ; } ; int main() { B objB( 3, 5 ) ; objB.out();}|对象数组是指每一数组元素都是对象的数组;
定义一个一维对象数组的格式:
类名 数组名【下标表达式】;
|当对象数组所属的类中包含无参的构造函数,也可以先定义,再给每个数组元素赋值;
|创建对象数组时使用构造函数,删除对象数组时使用析构函数;
二、总结及心得:
类作为自定义数据类型,具有封装性、继承性、多态性的特点,构造函数对数据进行初始,析构函数对数据进行删除的功能。其应用将主函数内容简化,将程序分为多个模块,无疑有利于书写长篇幅的系统,书写系统时应该分模块进行调节,虽然相比于C语言而言,其看似更繁,但可使我们转换思维方式,使我们拥有了“设计”的概念,类这一部分的学习对于本人这样初次接触的小白来说,无疑难如上青天,自知目前对类的认识不够深刻,虽然学习途中困难重重,但我觉不会轻言放弃的!