第8章 类

8

8.1 从结构体到类

1.struct class定义的自定义数据类型为了和 数据变量 的名称作区分名称以大写字母开头。

2.struct定义的复合数据的成分还可以是struct类型的,即可以嵌套

3.最初struct没有成员函数,结构体花括号和函数花括号是分开定义、互不关联的,结构体还和初始化语法相关联,构成一种语句形式,故要加花括号。后来class沿用了struct的形式,加了成员函数,仍然在花括号后面加分号,以示与函数的花括号相区别。

4.由数据类型创建的实体都是 对象,变量是对象的一种简单形式,由内部数据类型或结构型创建,“不”拥有操作。由类创建的对象拥有操作。

8.2 成员函数

8.2.1成员函数定义

1.成员函数调用时捆绑了对象,其实已含有参数,不必带形参如 date.print()。但普通函数需带形参如:printDate date

2.类定义中包含的成员函数默认声明为内联,编译时获得最佳运行性能,故尽量将成员函数写在类定义中。但破坏了类的可读性,而且复杂的函数或包含不适于内联运行的循环结构的函数不会被看作内联,故简单成员函数放定义放在类中,复杂的放在外面。

3.成员函数可以在类外部定义:void Date::print(){...}。可以显示的要求内联:

Inline void Date::print(){...}

8.2.2对象指针

1.对象指针间接访问成员函数的形式有两种(没区别):

(1)objectPointer->memberFunctionName(parameters);

(2)(*objectPointer).memberFunctionName(parameters);

Eg:  Date * dp = new Date();

       //Date * dp = new Date; //和上面的形式都正确

       dp->set(2000,12,6);

       if(dp->isLeapYear())

              //(*dp).print(); //和下面的形式都正确

              dp->print();

8.2.3常成员函数

常成员函数只对对象进行 操作,不会改变对象的值,故能成为常成员函数的应尽量写成常成员函数的形式

bool isLeapYear() const; //声明

inline bool isLeapYear() const{...} //定义

8.2.4重载成员函数

8.3.2操作符重载的性质:

1)不能创建新的操作符

2)个别操作符不能重载:双目里的::”, “.”,”.*三目操作符号? :”,以及typedefsizeof也不允许重载

3)重载后操作符的优先级和结合性不变

4)操作数的个数不变

5)操作符重载只针对自定义类型,即专门处理类对象。

6)不能意义相左。

8.3.3 值返回与引用返回

1)参数若为内置类型,返回一般不用引用; 若为类类型则一般用引用类型。

2)“+”操作得到的Point类型的结果并不要求驻留在一个确定的地方,仅要求能参与其他Point值的操作即可,故返回Point类的,并不用返回引用(局部变量返回引用造成错误)。它是临时的,随表达式而改变,在整个表达式求值结束时,也就结束了自己的生命。如果在动态内存中创建Point对象,这样可以返回引用,但是返回结果的表达式的性质决定其值的临时性,决定了动态内存空间会无端泄露。

<<”反返回的cout是特定于某个输出设备的流对象,是一个引用型的流。如果不是引用型而是值型的,则返回时要重新创建流对象,但其重叠操作时,因多次创建流而造成内存浪费。

8.3.4 增量操作符

1)一个前增量的操作结果与变量值是一直的,而且前增量的操作结果是左值(返回的结果是变量实体),操作可以连贯。后增量的操作结果是增量之前的变量值是临时变量,表达式计算结束后,临时变量消失,所以变量最终值与后增量的结果是不一致的。

2)增量操作符的重载:

A)前增量:参数为对象的引用,返回仍然是该对象参数的引用。

X& operator++(X &a);  ++a;

B)后增量:参数为对象的引用,返回为临时对象,为非引用的对象值。

X operator++(X &a, int b); a++

8.3.5 成员操作符

1)成员操作符与对象捆绑使用,被捆绑的对象即是第一个参数,故单目操作符的重载时没有参数,双目操作符重载时只有一个参数。

2cout<<a<<endl;(aPoint类型的对象)

因为<<的前置对象是流类型的cout,不是Point型,故不能设置成Point的成员,只能设置成普通函数,而且为了访问Point的私有数据,必须加关键字friend

8.4 程序结构

8.4.1 访问控制

1Struct class 的区别:

只有关键字和访问控制符的不同:struct默认访问控制符为publicclass默认为private

8.4.2类的程序结构

类定义写在头文件中,类的实现写在一个程序文件中,类的应用写在另一个文件中。

内联函数可以出现在不同的编译单位中,但在同一个编译单位(一个程序文件)只可以出现一次。

如果定义内联成员函数,则内联成员函数的定义必须写在头文件中,包含在头文件卫士中。

8.4.3 类作用域

类作用域包括类定义内部所有成员函数的定义体,类作用域中类的成员函数对类的数据成员和其他成员函数有无限制的访问权限。

类定义作用域包含类定义的花括号语句块,若果没有花括号,则为从类定义的全部代码。

8.6 静态成员

8.6.1 静态数据成员

1)当有的属性不是类中每个对象分别拥有的,而是共有的,同时这些属性又不能作为全局变量,因为他们属于某个类,而不属于有时间生命的程序。这时这些属性应该作为类的静态数据成员。

   2)静态数据成员存放在专属于其所在类的名空间的全局数据区中,为各对象所共有,所有对象使用一份拷贝。

3)因静态成员脱离对象而存在,故在所有的对象创建之前初始化。似乎像个全局变量但它专属于某个类。

       (4)静态数据在程序中具有唯一性,不能跟着类定义放在头文件中,而应放在类的实现代码中。在类定义中声明加static定义时不能再加static,在其前加其所在的类名和“::”。

8.6.2 静态成员函数

1)静态成员函数的调用方法有两种:

A)使用对象调用,像调用成员函数一样。B)使用类名加域操作符直接调用,这时将它看做属于某个名空间的函数。

2)静态成员函数在声明时加static,在类外实现时不能加static

3静态函数只能访问静态数据成员,不能访问数据成员。因为在对象未创建时静态函数已存在,但这时数据成员还未存在。成员函数既可以访问静态数据也可访问普通的数据成员。静态函数虽然不能访问普通数据成员,但并非不能访问私有数据成员,通过给其传递一个对象,可以访问对象的私有成员。

8.7 友元

1)将一个函数声明为友元,就可以访问类的私有数据。

2)友元经常用在操作符的重载中,比如<<不能作为类Point的成员函数,因为cout的前端是流对象,不能是Point对象,故<<不能作为成员函数,但可以将其声明为友元,这样就可以访问私有数据。

3)一个类的成员函数可以是另一个类的友元。

4)整个类可以声明为另一个类的友元,称为友类。友类的每个成员函数可以访问另一个类的私有成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值