先复习下引用的概念:
引用是变量的别名。引用必须初始化指向一块内存,切指向无法改变。
在某种场合以引用替代指针是C++区别于C的一个显著特征;引用内部是用指针实现的。
1. 如果将引用赋值给一个普通(非引用)变量会发生什么:
int glbVar = 10;
int& retRef()
{
return glbVar;
}
int main(int argc, char* argv[])
{
int tmp = 0;
int* ptr_tmp = &tmp;
tmp = retRef();
int& rtmp = retRef();
int* ptr_rtmp = &rtmp;
}
根据debug结果,可以看到将引用赋值给引用,rtmp和retRef()返回值相同,都是glbVar的别名(地址相同)。而将引用赋值给普通变量,tmp只是借用了glbVar的值而已,tmp和glbVar终究是2个变量(地址不同)。
2. 引用同样能实现多态:
class Base
{
public:
virtual void func() { cout << "baseFunc()" << endl; }
virtual void constFunc() const { cout << "constFunc()" << endl; }
};
class Inherit : public Base
{
public:
virtual void func() { cout << "inheritFunc()" << endl; }
};
void callFunc(const Base& ref)
{
const_cast<Base&>(ref).func();
//const obj only can call const func
//however non-const obj can call non-const & const func
ref.constFunc();
}
int main(int argc, char* argv[])
{
Base* pBase = new Inherit;
pBase->func();
(*pBase).func();
Base bObj = *pBase;
bObj.func();
callFunc(*pBase);
Inherit oInherit;
Base& rBase = oInherit;
rBase.func();
}
对照上述代码,逐一分析输出结果:
第一行通过指针实现多态,用指向子类的父类类型指针,调用到了子类的虚函数。
第二行和第一行一样,只不过指针解引用后,调用到了子类的虚函数。
第三行把指针解引用的结果(父类对象)赋予了父类指针,终究只能调用到父类的虚函数。
第四行通过引用形参实现多态,用父类类型的引用,调用到了子类的虚函数。(注意第四/五行,形参为const,const对象只能调用const函数;而非const对象既能调用const函数又能调用非const函数)
第六行通过引用变量实现多态,和第四行差不多。