1、合理运用inline函数
虽然说内联函数在理论上是可以提高程序的,但是要合理运用内联函数。对于一个代码量较小的函数进行的内联当然比较好,但是如果代码量过大,可能会造成代码膨胀引起系统颠簸(不合理的页面调度行为),得不偿失。其次,当你把一个函数设为内联函数,这对于编译器来说只是一个建议,而不是必然。编译器会自行选择是否要对于其进行内联。比如说函数包含的代码很多时,编译器可能就会选择不进行内联。构造函数和析构函数不适合内联,因为也许我们编写的代码比较少,但是用到的标准库类型的构造函数如果也是内联的那会是相当大的代码量(可以将编译器设置为诊断级,这样内联函数没有被内联时,它会给出警告信息)。再次,由于我们的选择不当,造成内联函数被编译器“外联,就会带来一定负面影响。”因为内联还是常常定义在头文件中,这样子就会出现多个.cpp文件都包含同一个内联文件的情况。一旦内联函数被外联,那么就会出现重定义的情况。编译器的解决方法是把当作静态函数来处理,这样避免了链接时错误却带来了额外开销。最后,内联函数中的静态对象常常表现出违反直觉的行为,因此,如果内敛函数中如果包含有静态对象,最好不用将它声明为内联。
2、实现接口与分离
类里面一般会包含有数据成员,比如说这样子的一个类:
#include “date.h”
#include “address.h”
class person
{
public:
string& get_string() const;
date& get_date() const;
private:
string name_;
date birth_date_;
address address_;
};
这个person类需要data、address的定义,因此person与data、address产生了编译依赖关系。当data、address改变它的实现时,包含person类的文件以及任何使用person的文件就必须重新编译。对于person类的用户来说这实在是令人讨厌。解决方法有两个。
其一,将其定义一个为句柄类,用户使用的是person,而具体的实现则是由personmpl类完成。如下:
person.h
class string;
class data;
class personmpl;
class person
{
public:
string& get_name() const;
date& get_date() const;
private:
personmpl *data;
};
而personmpl则是以前的person的实现
#include “date.h”
#include “address.h”
class personmpl
{
public:
string& get_name() const;
date& get_date() const;
private:
string name_;
date birth_date_;
address address_;
};
其二,将其定义为一个抽象基类(协议类),用户使用它要通过一个指向基类的指针。这个基类可以没有任何数据成员,具体的实现由派生类来完成。这个基类只是定义一套接口以及一个虚析构函数。例如:
class person
{
public:
virtual ~person();
virtual string& get_name() const;
virtual date& get_date() const;
};
class real_person:public person
{
public:
real_person(const string& name,const date& birth,const address& addr);
string& get_name() const;
date& get_date() const;
private:string name_;
date birth_date;
address addr;
}
这个person纯虚类没有构造函数,那么怎么产生一个指向person的指针或者引用呢。可以用工厂函数实现。在person类中定义一个静态函数。例如:
class person
{
...同上
static person* make_person(const string& name,const date& birth,const address& addr);
};
person* person::make_person(const string& name,const date& birth,const address& addr)
{
return new real_person(name,birth,addr);
};
句柄类和协议类实现了接口和实现的分离,降低了文件的编译依赖性。