一个类中的成员变量是另一个类的类类型,赋值问题分为引用,不引用两类
如先定义TESTB类
class TESTB
{
public:
TESTB(){ b_ = 3.7; }
~TESTB(){}
void change(){ b_ = 9.0; }
float getb(){ return b_; }
private:
float b_;
};
在类TESTA中有一个TESTB类的对象作为成员(先加TESTB类所在的头文件)
1、不加引用
class TESTA
{
public:
TESTA(){}
~TESTA(){}
void assign(TESTB tb){ tb_ = tb; }//这里加不加引用只影响执行效率不影响结果
public:
TESTB tb_;
};
(1)如执行了void assign(TESTB tb){ tb_ = tb; }显式赋值,则会赋给一个当前值
int main()
{
TESTB bb;//这里bb的tb_为3.7
bb.change();//这里bb的tb_应为9.0了
TESTA a;
a.assign(bb);//这里执行了显式赋值tb_ = tb
std::cout << a.tb_.getb() << std::endl;
return 0;
}
输出结果为9.0,因为bb的tb_执行到9.0的时候将本身赋给a.tb_
当然不执行bb.change()的话,输出结果为3.7,因为bb的tb_执行到3.7
结论:不加引用,显式赋值,TESTA的对象的成员tb_得到的是实参的当前值
(2)如未执行void assign(TESTB tb){ tb_ = tb; }显式赋值,则会相当于新实例化一个对象,其变量都是TESTB构造函数中指定的
int main()
{
TESTB bb;//这里bb的tb_为3.7
bb.change();//这里bb的tb_应为9.0了
TESTA a;
//a.assign(bb);//这里没有执行显式赋值tb_ = tb
std::cout << a.tb_.getb() << std::endl;
return 0;
}
结论:不加引用,未显式赋值,TESTA的对象的成员tb_相当于被初始化了,当然后面再显式赋值时,再改变
2、加引用(此时会提示:必须初始化引用类型成员),因此在构造函数中初始化tb_变量,必须在构造函数中使用列表的形式初始化,不能在函数体中使用“=”
class TESTA
{
public:
TESTA(TESTB& b):tb_(b){ }//形参也必须是引用
~TESTA(){}
void assign(TESTB tb){ tb_ = tb; }//这里加不加引用只影响执行效率不影响结果
public:
TESTB& tb_;//引用
};
此时相当于显式赋值了,得到的是什么值就是什么值
int main()
{
TESTB bb;//3.7
bb.change();//9.0
TESTA a(bb);//将成员9.0的赋给a的成员
std::cout << a.tb_.getb() << std::endl;
return 0;
}
输出结果是9.0,因为赋值的时候已经是9.0了
再看
int main()
{
TESTB bb;
TESTA a(bb);//得到3.7
std::cout << a.tb_.getb() << std::endl;
bb.change();//bb改变
std::cout << a.tb_.getb() << std::endl;
return 0;
}
第一次输出3.7,因为得到了3.7的值;第二次输出9.0,因为是引用a.tb_相当于bb的别名,两者同时变化
结论:1、加引用TESTB& tb_,必须在TESTA构造函数中以引用的形式传入一个TESTB 对象,且以列表方式初始化;2、a.tb_相当于bb的别名,两者同时变化
备注:至于TESTB& tb_;是私有还是公有的问题,只影响访问属性,也可以在TESTA中构造get函数访问,不影响上述结论
当我们要利用另一类对象的一些操作结果并在本类中改变该结果时,要采用引用的形式,见2
当我们要利用另一类对象的一些操作结果但是不想由本类的操作改变该结果时,不用引用,单写一个赋值函数并执行,见1(2)