C++编译期与运行期
2011-10-06 14:39
253 查看
看这样一段代码。
view plain
#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信息定义为空。因为编译消耗的时间是一次性的,而运行的效率是直接呈现给用户的。由这种节约时间的方法,我们可以发现把很多函数的判断和计算放在编译期,会大大节约运行的时间,提供运行效率,但是编译器并不是万能,所以编译期能做的工作还是十分的有限。
转自:/article/10100282.html
view plain
#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信息定义为空。因为编译消耗的时间是一次性的,而运行的效率是直接呈现给用户的。由这种节约时间的方法,我们可以发现把很多函数的判断和计算放在编译期,会大大节约运行的时间,提供运行效率,但是编译器并不是万能,所以编译期能做的工作还是十分的有限。
转自:/article/10100282.html
相关文章推荐
- C++编译期多态与运行期多态
- C++编译期多态与运行期多态
- c++ 编译期与运行期总结
- c++有关编译期和运行期的访问
- C++的运行期多态和编译期多态
- 关于C++多态的一些思考(编译期绑定和运行期绑定)
- C++编译期多态与运行期多态
- C++:运行期断言和编译期断言
- C++编译期多态与运行期多态
- Effective C++第七章-模板和泛型编程之编译期多态(运行期多态)和隐式接口(显式接口)
- 转载:C++编译期多态与运行期多态
- C++中编译期多态机制和运行期多态机制之间的区别
- c++ 之 编译期多态&运行期多态
- 基础备忘:C++编译期多态与运行期多态
- c++ 编译期与运行期 总结
- C++编译期多态与运行期多态
- 多态性之编译期多态和运行期多态(C++版)
- C++编译期多态与运行期多态
- C++ 函数运行期和编译期运行
- C++编译期多态与运行期多态