const与&引用

书上的一个例子

#include <iostream.h>
class Complex  
{  
public:  
    Complex():real(0),imag(0){};  
    Complex(double r, double i):real(r),imag(i){};  
    Complex(double r):real(r),imag(0){};  // 定义转换构造函数  
  
    void Print(){  
        cout<<"real = " << real <<" image = "<<imag<<endl;  
    }  
    friend Complex operator+(Complex c,const Complex b)
	{  
        return Complex(b.real + c.real, b.imag + c.imag);       
    }  
private:  
    double real;  
    double imag;  
};  
  
int main()  
{
    Complex c;  
    c = 1.2;  // 调用转换构造函数将1.2转换为Complex类型  
    c.Print();  
    Complex c1(2.9, 4.2);  
	double d = 3.1;
    Complex c2 = c1 + 2.1; // 调用转换构造函数将3.1转换为Complex类型  
    c2.Print();  
    return 0;  
}

1.

这是没问题的,下面我们先看看&引用赋值的问题

int a = 12;
int &b = a;//可以
int &c = 12;//无法 (int & ! const int)

第三句是不许的,或许我们认为&c = 12是把12这个类型值取别名可是

这个初始化错误提示明显告诉我们这是个赋值操作,而不是把int类型变量赋值int &

所以可以这样

const int &g = 12;

2.

从上面的错误我们可以猜想把int a = 12在vc编译器是这样的12是个const int常数类型的,经过=后它交给了int的类型

为了验证一下

const int a = 12;
int b = a;

编译通过

但是

const int a = 12;
int &b = a;


说明了一个引用的特点,不能将一个const T的类型交给T &类型

但是可以const T赋给 const T&

3。

我们回到上面的例子,且修改一下

    friend Complex operator+(Complex &c,Complex &b)
    {  
        return Complex(b.real + c.real, b.imag + c.imag);       
    }  

这时会出现

如果了解了前面的1,2知识点,我们会发现我们把一个1.2 => const 变量类型交给了 &类型,上面我们讨论过是不予的,但是该程序中我们是想通过类型转换构造器来把const 类型的int 即1.2转换成Complex,然后再交给该程序中的友元重载函数的第二个参数,这样以来思路是没错的

但是这样

    friend Complex operator+(Complex &c,const Complex &b)
	{  
        //return Complex(b.real + c.real, b.imag + c.imag); 
		return NULL;
    } 

就可以编译通过了,

再看看一个矛盾的地方

#include <iostream.h>
class Complex  
{  
public:  
    Complex():real(0),imag(0){};  
    Complex(double r, double i):real(r),imag(i){};  
    Complex(double r):real(r),imag(0){};  // 定义转换构造函数  
  
    void Print(){  
        cout<<"real = " << real <<" image = "<<imag<<endl;  
    }  
    friend Complex operator+(Complex &c, Complex &b)
	{  
        //return Complex(b.real + c.real, b.imag + c.imag); 
		return NULL;
    }  
private:  
    double real;  
    double imag;  
};  
  
int main()  
{
    double d = 3.1;
    Complex c;  
    c = d;  // 调用转换构造函数将1.2转换为Complex类型 ,隐式转换成功

    c.Print();  
    Complex c1(2.9, 4.2);  
	//double d = 3.1;
    Complex c2 = c1 + d; // 调用转换构造函数将3.1转换为Complex类型 ,但是看看下面的报错,上面都隐式转换成功了,这里却不行
    c2.Print();  

    return 0;  
}




4.那么我们猜想是不是因为 表达式中 + 1.2 是个数字常量导致的?

修改一下测试一下

#include <iostream.h>
class A
{
public:
	double value;
	A(double para)
	{
		value = para;
	}
};
class Complex  
{  
public:  
    Complex():real(0),imag(0){};  
    Complex(double r, double i):real(r),imag(i){};  
    Complex(A r):real(r.value),imag(0){};  // 定义转换构造函数  
  
    void Print(){  
        cout<<"real = " << real <<" image = "<<imag<<endl;  
    }  
    friend Complex operator+(Complex &c, Complex &b)
	{  
        //return Complex(b.real + c.real, b.imag + c.imag); 
		return NULL;
    }  
private:  
    double real;  
    double imag;  
};  
  
int main()  
{
    double d = 3.1;
    Complex c;  
    //c = d;  // 调用转换构造函数将1.2转换为Complex类型  

    c.Print();  
    Complex c1(2.9, 4.2);  
	//double d = 3.1;
	A a(12);
    Complex c2 = c1 + a; // 调用转换构造函数将3.1转换为Complex类型  
    c2.Print();  

    return 0;  
}

结果还是报错

同样我们

    friend Complex operator+(Complex &c, const Complex &b)
	{  
        //return Complex(b.real + c.real, b.imag + c.imag); 
		return NULL;
    }  


就可以通过

5.原因猜想,在&类型被初始化时,vc并没有优先考虑隐式转换,而是直接进行判断类型是否匹配

基于4,我们再测试一次来验证我们的猜想

double d = 3.1;
A a(12);
Complex &c = a; 

报错


而这样子

double d = 3.1;
A a(12);
Complex c = a;  // 调用转换构造函数将1.2转换为Complex类型  
Complex &c0 = c;
c0.Print();

这样 &c0 = c 的c变量是类型确定的,所以可以成功

Note:

不过我们在这里可看到其实C++的隐式转换是允许组合的例如

double d = 3.1;
A a(12);
Complex c = 11;  // 调用A的转换构造函数将1.2转换为A类型,接着调用Complex的转换构造器将A类型转换为Complex  
//*****************************************//

那么我们要怎么才能把Complex &c = a赋值成功呢?我们可以使用常量类型的引用

即const Complex &c = a 这样就能成功,把上面的改一下

double d = 3.1;
A a(12);
const Complex &c = a; 

这样就没问题了,所以在隐式转换(C++使用构造器实现)时且要把最终装换的结果赋给&类型,&类型就必须为const类型的,才能让隐式转换成功

不过这里还有一个问题,就是用这种方法能不能解决隐式转换的组合情况呢?答案是不行的,看下一个

6.上面5的Note中我们实现了隐式转换的组合

//double d = 3.1;
//A a(12);
Complex c = 12; 

等于

//double d = 3.1;
A a(12);
Complex c = a;

我们可以

double d = 3.1;
A a(12);
const Complex &c = a; 

但是不可以

double d = 3.1;
A a(12);
const Complex &c = 12;



估计这是编译器的能力所限吧

6.

实践总结,如果通过

=> 表示转换

隐式转换A => B时,且B是个引用类型那么B必须是const类型的

--表示隐式组合

隐式转换A -- B =>C 即隐式转换两次时不能把声明为&,根据上面的规则,A转换为B时,B无法是个const B因为他是构造器构造出来的B


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值