细说构造函数中的常引用 ( 2006-10-30 19:25 )
构造函数用于对象的初始化。这一点相信大都明白。但是:构造函数不能被继承,基类是要先初始化的,基类初始化工作如何做?
C++是通过代码调用,以实现基类初始化在派生类的前面,单一继承的语法如下:
<派生类名>::<派生类名>(<参数表>):<基类名>::<基类名>(<参数表>)
{
<派生类成员的初始化代码>
}
也就是说:在派生类构造函数后面加上“:”,在后面列出要调用的基类的构造函数。
如:CMyTrigon::CMyTrigon(int iheight,int iwidth) : CMyRect(iheight, iwidth)
如果多继承,则加“,”再一一列出要调用的基类的构造函数。列出时要注意按派生的顺序。
需要注意的是:
派生类构造函数必须负责读取基类构造函数中所需的参数。如上例,int iheight,int iwidth是读取基类所要的参数。CMyRect(iheight, iwidth)是在派生类读到参数后,对基类派生类的调用。
C++类的构造函数的参数与普通函数能数一样,同样也有三种形式:
1、实参,即通过值传递。
如:CTrigon(int nWidth,int nHeight)
2、形参,通过指针传递。
如:CRondInTrigon(const CRond *rond,int nWidth,int nHeight)
3、形参,通过引用传递。
如:CRondInTrigon(const CRond &rond,int nWidth,int nHeight)
为什么要通过形参来传递呢?
从上面代码就可以发现,当一个类中的成员是另一个类的对象,或者是结构等,我们就必须使用指针或引用。否则,我们没有其它办法传递该类参数。
这里面有一个非常特别的问题,那就是,凡是通过引用或指针传递的,都需要用常指针或常引用来传。为什么?
首先要了解,const是做什么用的?const是用来限定变量中的数据不可改变。但是对指针中的地址或引用中的地址无任何作用。也就是说:
下面的函数将会出错:
void swap(const int *x, const int *y)
{
int tmp=*x;
*x=*y;
*y=tmp;
}
同样,下列函数一样也会出错:
void swap(const int &x, const int &y)
{
int tmp=x;
x=y;
y=tmp;
}
原因就在于,const是对数据进行保护,使其不可写。但是,如果我们改变其指针所指的变量,这种改变就不会出错。为什么?指针或引用主要依据地址,而地址是程序中的辅助数据。我们要保护的是数据不能改变。
如,下面程序就不会出错。但是却有两个典型的错误:
因为通过指针或引用,我们可以返回多个数据。但我们不能改变指针或引用。下例是要改变指针。则需要用指针的指针才行。同时,下例中返回局部指针也是不对的。因为局部指针在函数运行结束后将不存在。
#include
void nswap(const int *x, const int *y)
{
int m=12;
int n=13;
int *j=&m;
int *k=&n;
x=j;
y=k;
}
main()
{
int m=21;
int n=31;
int *x=&m;
int *y=&n;
nswap(x,y);
printf("%d;%d\n",*x,*y);
}
那么,我们可以假设,对于传入对象的构造函数,不用const,结果会如何?
幸运时,你不会出错。但是不幸情况很多。因为,你无法预料,在你的程序中何时改变参数的数值。这时,不想要的结果就出现了。尤其是在派生类的复杂构造函数。
像:CRondInTrigon(const CRond *rond,int nWidth,int nHeight)
这个构造函数,你总不想要,初始化了rond,再构造CRondInTrigon后,发现,你在rond的初始化数据已不是原来的数据吧?有const就会有写保护而及时指出你的错!
有人说,派生函数中的参数,最好加上const,实际上这种说法是不对的!
C++还有一种特殊的构造函数,那就是为自己建一副本的构造函数——拷贝构造函数。原因是因为:已有一个在使用的对象,现在要用这个对象的数据重新构造一个新对象。如果将原对象中的数据取出来,则需要调用其中的相关成员函数才行。用拷贝构造函数可以复制指定对象的数据到本对象。
下面就是一个实例:
//注意:此类不是MFC的CRECT,而是自定义类
CMyRect(const CmyRect &rt) {
If (&rt !=this) //如果rt不是我,这是条件,不能自我复制。
//(这也算是this的一个用法)
{
//复制成员
height= rt.GetHeight();
width= rt.GetWidth();
left=rt.nleft;
top= rt.ntop;
}
}
在此类构造函数中,一样需要用const进行限定,因为,你只要复制,并不想改变你原有的对象的数据。
总之,如果你是用指针虞引用传入构造函数,你需要加上const以保护传入的数据。
当然,需要补充的是,常引用可以使参数有默认值,这也是非常有用的:
像以下代码:
const int &m=2;
编译器先将2赋给临时变量。然后再引用临时变量
即:
int tmp=2;
const int &m=tmp;
由此,我们可以用在函数中,而不是这样写程序,因为这样是没有必要的。下面是样例程序:
#include
int nswap(int &x,const int &y=3)
{
int k=y;
x+=2;
k+=5;
return(x*k);
}
void main()
{
int m=2;
int n=1;
int t=nswap(m,n);
printf("%d;%d;%d\n",t,m,n);
int p=nswap(m);
printf("%d;%d;%d\n",p,m,n);
}
也就是说,以引用传参,是可以有默认值的。要做到有默认值,必须要用常引用才行!
分享到:
相关推荐
细说javascript函数从函数的构成开始.docx
细说matlab中的max函数.docx
细说Linux 细说Linux 细说Linux 细说Linux 细说Linux 细说Linux
新的《细说PHP中的CMS》——高洛峰 可以用来进行学习,对于初学PHP的很有好处
正是因为有了这些烦恼才让javascript函数值得我们寻味,我想从函数的构成来细说函数,这听起来像是一句废话,讲任何东西当然是从构成去谈,但是由于javascript函数你确实捉摸不了它的形态,因此这里我是从一个标准...
对于PHP应用开发的新手而言,《细说PHP》不失为一本好的入门教材,内容既实用又全面,辅以视频教程,使读者轻松掌握所学知识
细说php是lamp兄弟连出版的书籍,这里提供的是细说php的源代码.
细说linux pdf 兄弟连(lampbrother)李明linux课程pdf
PHP课件 细说PHP
《细说PHP(第2版)》自出版以来,销售一路在同类书籍中领先,已成为PHP学习者首选的工具书。为了可以让读者携带方便及更精准地掌握PHP的重点、要点,同时能使之作为大学计算机系PHP教材普及,特别推出《细说PHP精要...
韩顺平细说servlet笔记
细说php
图表细说电子元器件 图表细说电子元器件(全部)图表细说电子元器件(全部)
韩顺平_细说servlet_笔记__完整版
由于上传文档大小受到限制只能分卷压缩。 《细说PHP》开发Web应用程序PHP是最理想的工具,易于使用、功能强大、成本低廉、高安全性、开发速度快且执行灵活。...系统地介绍了PHP的相关技术及其在实际Web开发中的应用。
《细说php(第2版)》自出版以来,销售一路在同类书籍中领先,已成为php学习者首选的工具书。为了可以让读者携带方便及更精准地掌握php的重点、要点,同时能使之作为大学计算机系php教材普及,特别推出《细说php精要版...
《细说PHP》配套源码
图表细说电子元件 图表细说电子元件 绝对经典