1、按值传递对象与传递引用:
通常,编写使用对象作为参数的函数时,应按引用而不是按值来传递对象。这样做的原因之一是提高效率。按值传递对象涉及到生成临时拷贝,即调用复制构造函数,然后调用析构函数。调用这些函数需用时间,复制大型对象比传递引用花费的时间要多的多。如果函数不修改对象,应将参数声明为const引用。
按引用传递对象的另一个原因是,在继承使用虚函数时,被定义为接受基类引用参数的函数可以接受派生类。
虚方法:P471
设计基类时,必须确定是否将类方法声明为虚拟的。如果希望派生类能够重新定义方法,则应在基类中将方法定义为虚拟的。
//按引用传递
void show(const Brass & rba)
{
rba.ViewAcct();
cout<<endl;
}
//按值传递
void inadequate(Brass ba)
{
ba.ViewAcct();
cout<<endl;
}
假设将派生类参数传递给上述两个函数:
BrassPlus buzz("Buzz Parsec",00001111,4300);
show(buzz);
inadequate(buzz);
show()函数调用使rba参数成为BrassPlus对象buzz的引用,因此,rba.ViewAcct()被解释为BrassPlus版本。但在inadequate()函数中,ba是Brass(const Brass &)构造函数创建的一个Brass对象,因此,ba.ViewAcct()被解释为Brass版本,所以只有buzz的Brass部分被显示。
如果希望派生类可以重新定义基类的方法,则可以使用关键字virtual将它声明为虚拟的,这样对于通过指针或引用访问的对象,能够根据对象类型来处理,而不是根据引用或指针的类型来处理。具体地说,基类的析构函数通常应当是虚拟的。
2、返回对象和返回引用
返回对象涉及到生成返回对象的临时拷贝,这是调用函数的程序可以使用的拷贝。因此,返回对象的时间成本包括调用复制构造函数来生成拷贝所需的时间和调用析构函数删除拷贝所需的时间。返回引用可以节省时间和内存。
函数不能返回在函数中创建的临时对象的引用,因为当函数结束时,临时对象将消失,在这种情况下应返回对象,以生成一个调用程序可以使用的拷贝。
通常的规则是,如果函数返回在函数中创建的临时对象,则不要使用引用。例如,下面的方法使用构造函数创建一个新对象,然后返回该对象的拷贝:
Vector Vector::operator+(const Vector & b)const
{
return Vector(x+b.x,y+b.y);
}
如果返回的是通过引用或指针来传递给它的对象,则应按照引用传递。例如,下面的代码按引用返回调用函数的对象或作为参数传递给函数的对象:
const Stock & Stock::topval(const Stock & s)const
{
if(s.total_val>total_val)
return s;
else
return *this;
}