`
bardo
  • 浏览: 372960 次
  • 性别: Icon_minigender_1
  • 来自: 上海
博客专栏
D1407912-ab64-3e76-ae37-b31aa4afa398
浅述PHP设计模式
浏览量:11648
9d6df9f7-91da-3787-a37c-0e826525dd5d
Zend Framewor...
浏览量:9999
85b628bd-a2ed-3de2-a4b1-0d34985ae8b6
PHP的IDE(集成开发环...
浏览量:9359
社区版块
存档分类
最新评论

细说构造函数中的常引用

    博客分类:
  • VC
阅读更多
细说构造函数中的常引用 ( 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);

}
也就是说,以引用传参,是可以有默认值的。要做到有默认值,必须要用常引用才行!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics