您的位置:首页 > 其它

编译期与运行期

2009-12-31 15:19 155 查看
看这样一段代码。

#include <iostream>
using namespace std;

class A{
public:
virtual void f(){cout<<"A"<<endl;}
};

class B:public A
{
private:
void f(){cout<<"B"<<endl;}
};

int main()
{
A* pA = new B();
pA->f();
return 0;
}


出现了很有趣的结果,在main函数中,访问到了B类中的私有方法。为什么会出现这样的结果呢?

一般来说外部对象访问类的私有成员,除非是友元,否则在编译的时候就会报错,但是上面那段代码却可以正常的编译通过。

C++因为支持面向对象编程,制订了一系列实现策略的语言机制。其中,各种各样的“限制”主要是出现在编译时:因此如果直接B d; d.f(); 就会导致编译错误:编译器发现 B::f()是B类的私有成员函数,因此拒绝这样的访问。

这里我们可以区分类和对象:类是编译期的概念,也是“访问权限”、“成员数据”、“成员函数”这几个概念的“作用域”。而对象的作用域是运行期。它包括类的实例、引用和指针。
A *pA = new B();
这里 pA 是一个 A* , 所以就作为一个A类的指针参与了编译;因此从pA调用f()在编译器眼中,就是调用了A类的公开成员函数f()因此通过编译;然后在运行时,由于多态作用pA调用的f()是派生类的f()成员函数。虽然这时f()是private成员函数,但是由于 private/public 这些访问控制是编译时的限制,在运行时无效,所以B::f() 被成功调用。如果能够理解这两个在不同时间作用的概念,这个问题就很好理解.

由这个问题,就引出了编译期和运行期的概念。

顾名思义,编译期指的是编译器在编译代码的时候,而运行期指的是程序运行的时候。

在大型系统中,log信息的管理是一项十分庞大的工程。通常来说log分为两种,一种是调试的log信息,一种是出错的Log信息,前者只对本模块的开发工程师可见,后者本系统的工程师和测试工程师可见。由此就引入了log信息的管理,我们通常有release版本和debug版本,release版本的log信息只限于出错log,debug则输出本模块的log。闲话扯远了,回归正题。

如何来控制log信息的输出,也就是程序如何判断是否输出log。很明显我们需要判断语句,那么如何使用判断语句才能保证最好的效果。这里有两种方法。

设定全局const变量,在打印函数中根据全局变量来判断。这样的实现也很简洁,修改起来也很方便。

const bool g_debug 1

void Log(char* str)

{

if (g_debug){

printf(str);

}

}

还有一种方法,利用宏来控制Log的输出,用全局宏代替全局变量,宏函数代替全局函数。

#define DEBUG

#ifdef DEBUG

#define LOG(m) /

{/

printf(m);/

}/

#else

#define LOG(m)

#endif

有经验的程序员肯定一眼就看出来第二种Log输出方式比较好。第一种的判断是在运行期,而第二种的判断是在编译期。第一种在每次运行log函数的时候都会去判断全局变量,而第二种是在编译的时候就已经将不需要的Log信息定义为空。因为编译消耗的时间是一次性的,而运行的效率是直接呈现给用户的。由这种节约时间的方法,我们可以发现把很多函数的判断和计算放在编译期,会大大节约运行的时间,提供运行效率,但是编译器并不是万能,所以编译期能做的工作还是十分的有限。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: