注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

snoopyxdy的博客

https://github.com/DoubleSpout

 
 
 

日志

 
 

C++笔记(三)  

2012-11-21 12:58:27|  分类: C++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
继续上篇,C++的类

1、const和mutable
既要使数据能在一定范围内共享,又要保证它不被任意修改,使用const,即把有关的数据定义为常量。

Time const t1(12,34,46);//t1是常对象

类名 const对象名[(实参表列)];
等价于
const 类名对象名[(实参表列)];
如果一个对象被声明为常对象,则不能调用该对象的非const型的成员函数(除了由系统自动调用的隐式的构造函数和析构函数)。

const Time t1(10,15,36); //定义常对象t1
t1.get_time( ); //企图调用常对象t1中的非const型成员函数,非法

现在,编译系统只检查函数的声明,只要发现调用了常对象的成员函数,而且该函数未被声明为const,就报错。

void get_time( ) const; //将函数声明为const

这表示get_time是一个const型函数,常成员函数可以访问常对象中的数据成员,但仍然不允许修改常对象中数据成员的值。
有时在编程时有要求,一定要修改常对象中的某个数据成员的值,ANSI C++考虑到实际编程时的需要,对此作了特殊的处理,对该数据成员声明为mutable lteaumb,如

mutable int count; //把count 声明为可变的数据成员

这样就可以用声明为const的成员函数来修改它的值。

2、常对象成员
其作用和用法与一般常变量相似,用关键字const来声明常数据成员。常数据成员的值是不能改变的。注意:只能通过构造函数的参数初始化表对常数据成员进行初始化。
如在类体中定义了常数据成员hour:

const int hour; //声明hour为常数据成员

不能采用在构造函数中对常数据成员赋初值的方法。
在类外定义构造函数,应写成以下形式:

Time∷Time(int h):hour(h){} //通过参数初始化表对常数据成员hour初始化

常对象的数据成员都是常数据成员,因此常对象的构造函数只能用参数初始化表对常数据成员进行初始化。

3、常成员函数
一般的成员函数可以引用本类中的非const数据成员,也可以修改它们。如果将成员函数声明为常成员函数,则只能引用本类中的数据成员,而不能修改它们,例如只用于输出数据等。如

void get_time( ) const; //注意const的位置在函数名和括号之后

const是函数类型的一部分,在声明函数和定义函数时都要有const关键字,在调用时不必加const。
a\如果在一个类中,有些数据成员的值允许改变,另一些数据成员的值不允许改变,则可以将一部分数据成员声明为const,以保证其值不被改变,可以用非const的成员函数引用这些数据成员的值,修改非const数据成员的值。
b\如果要求所有的数据成员的值都不允许改变,则可以将所有的数据成员声明为const,或将对象声明为const(常对象),然后用const成员函数引用数据成员,这样起到“双保险”的作用,切实保证了数据成员不被修改。
c\如果已定义了一个常对象,只能调用其中的const成员函数,而不能调用非const成员函数(不论这些函数是否会修改对象中的数据)。这是为了保证数据的安全。如果需要访问对象中的数据成员,可将常对象中所有成员函数都声明为const成员函数,但应确保在函数中不修改对象中的数据成员。不要误认为常对象中的成员函数都是常成员函数。常对象只保证其数据成员是常数据成员,其值不被修改。如果在常对象中的成员函数未加const声明,编译系统把它作为非consttscon成员函数处理。
还有一点要指出:常成员函数不能调用另一个非const成员函数。


4、对象的常引用
一个变量的引用就是变量的别名。实质上,变量名和引用名都指向同一段内存单元。如果形参为变量的引用名,实参为变量名,则在调用函数进行虚实结合时,并不是为形参另外开辟一个存储空间(常称为建立实参的一个拷贝),而是把实参变量的地址传给形参(引用名),这样引用名指向实参变量。

#include <iostream>
using namespace std;
class Time
{public:
Time(int,int,int);

int hour;
int minute;
int sec;
};
Time∷Time(int h,int m,int s) //定义构造函数
{
hour=h;
minute=m;
sec=s;
}
void fun(Time &t) //形参t是Time类对象的引用
{
t.hour=18;

}
int main( )
{Time t1(10,13,56); // t1是Time类对象

fun(t1); //实参是Time类对象,可以通过引用来修改实参t1的值
cout<<t1.hour<<endl; //输出t1.hour的值为18
return 0;
}

如果不希望在函数中修改实参t1的值,可以把引用变量t声明为const(常引用),函数原型为

void fun(const Time &t);


5、const类型小结
Time const t1;                    t1是常对象,其值在任何情况下都不能改变
void Time∷fun( ) const     fun是Time类中的常成员函数,可以引用,但不能修改本类中的数据成员
Time *const p;                   p是指向Time对象的常指针,p的值(即p的指向)不能改变
const Time  *p;                  p是指向Time类常对象的指针,其指向的类对象的值不能通过指针来改变
Time &t1=t;                       t1是Time类对象t的引用,二者指向同一段内存空间

6、new和delete
可以用new运算符动态建立对象,用delete运算符撤销对象。如果已经定义了一个Box类,可以用下面的方法动态地建立一个对象:

Box *pt; //定义一个指向Box类对象的指针变量pt
pt=new Box(12,15,18); //在pt中存放了新建对象的起始地址,对新建立的对象进行初始化
cout<<pt->height; //输出该对象的height成员
cout<<pt->volume( ); //调用该对象的volume函数,计算并输出体积

调用对象既可以通过对象名,也可以通过指针。用new建立的动态对象一般是不用对象名的,是通过指针访问的;在不再需要使用由new
建立的对象时,可以用delete运算符予以释放。

delete pt; //释放pt指向的内存空间


7、对象的复制

Box box2(box1);

其作用是用已有的对象box1去克隆出一个新对象box2。
其一般形式为
类名 对象2(对象1);
用对象1复制出对象2。box2的构造函数就是:

//The copy constructor definition.
Box∷Box(const Box &b)
{height=b.height;
width=b.width;
length=b.length;
}

也可以使用

Box box2=box1,box3=box2;

这种形式看起来很直观,用起来很方便。但是其作用都是调用复制构造函数。

8、多个对象共享数据

class Box
{public:
int volume();
private:
static
int height; //把height定义为静态的数据成员
int width;
int length;
};

如果希望各对象中的height的值是一样的,就可以把它定义为静态数据成员,这样它就为各对象所共有,而不只属于某个对象的成员。
  评论这张
 
阅读(724)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016