本文是对<<Ruminations on C++>>中自己跟踪自己的类这章内容的一个读书笔记,其中也加上了自己的理解,这个内容页给了我很大的启发,让我更加惊叹
c++是如此的强大,令人魂牵梦萦。
本文的主要内容是阐述以何种方式提供有关函数执行和类操作的调试信息,调试信息在我们项目开发和调试中是非常重要的,很多时候我们是通过查看程序运行的log来
分析程序的问题所在,毫无疑问,准确而高效的log会帮助我们很快定位出程序出错在哪个位置。所以我们需要研究怎么样提供有效的调试信息
首先看下面这个简单的跟踪类:
#include <iostream>
using namespace std;
class Trace
{
public:
Trace()
{
cout<<"Hello."<<endl;
}
~Trace()
{
cout<<"Goodbye."<<endl;
}
};
void foo()
{
Trace t;
cout<<"Do something in function foo()."<<endl;
}
int main()
{
foo();
return 0;
}
下面是程序的输出:
用这种方法我们可以通过log可以很清楚的看到程序执行到函数foo了,也就是通过程序的输出“hello”和“Goodbye”知道程序运行到foo这个函数了。换句话说我们通过
在函数中插入了一个Trace类对象来知道该函数什么时候被调用的。
但是我们的程序肯定不止一个函数,如果我们需要对多个函数进行跟踪,这种方法就不太适用了,因为无论在哪个函数里程序都输出“hello"和"Goodbye”,
我们并不知道这些信息是哪个函数输出的。
为了解决这个问题,下面对Trace类进行了改进
#include <iostream>
using namespace std;
class Trace
{
public:
Trace(const string start, const string s):end(s)
{
cout<<start<<endl;
}
~Trace()
{
cout<<end<<endl;
}
private:
string end;
};
void foo()
{
Trace t("Begin foo()", "End foo()");
cout<<"Do something in function foo()."<<endl;
}
int main()
{
foo();
return 0;
}
下面是程序的输出:
这个Trace类做了一些改进,更加智能一些,通过向构造函数传递了两个参数,一个参数在Trace对象构造时打印出来,另一个在Trace对象析构时打印出来,
这样我们就可以向构造函数传递与函数名相关的参数信息了。这个Trace类应该很接近于实用了,可是当我们使用的过程中会发现这个类会存在几个问题:
1. 打印的信息有很多共同点,不利于我们查看,比如都以Begin开始,End结束等,有人也许不明白,打印的信息由我们传递给Trace构造函数的参数来决定,但是试想以下
我们有很多个函数,我们不太可能在每个函数中给Trace对象传递差异很大的字符串,这就像C++为什么要引入namespace来解决命名冲突的问题。
2. 众所周知,程序分为Release版和Debug版本
c++是如此的强大,令人魂牵梦萦。
本文的主要内容是阐述以何种方式提供有关函数执行和类操作的调试信息,调试信息在我们项目开发和调试中是非常重要的,很多时候我们是通过查看程序运行的log来
分析程序的问题所在,毫无疑问,准确而高效的log会帮助我们很快定位出程序出错在哪个位置。所以我们需要研究怎么样提供有效的调试信息
首先看下面这个简单的跟踪类:
#include <iostream>
using namespace std;
class Trace
{
public:
Trace()
{
cout<<"Hello."<<endl;
}
~Trace()
{
cout<<"Goodbye."<<endl;
}
};
void foo()
{
Trace t;
cout<<"Do something in function foo()."<<endl;
}
int main()
{
foo();
return 0;
}
下面是程序的输出:
用这种方法我们可以通过log可以很清楚的看到程序执行到函数foo了,也就是通过程序的输出“hello”和“Goodbye”知道程序运行到foo这个函数了。换句话说我们通过
在函数中插入了一个Trace类对象来知道该函数什么时候被调用的。
但是我们的程序肯定不止一个函数,如果我们需要对多个函数进行跟踪,这种方法就不太适用了,因为无论在哪个函数里程序都输出“hello"和"Goodbye”,
我们并不知道这些信息是哪个函数输出的。
为了解决这个问题,下面对Trace类进行了改进
#include <iostream>
using namespace std;
class Trace
{
public:
Trace(const string start, const string s):end(s)
{
cout<<start<<endl;
}
~Trace()
{
cout<<end<<endl;
}
private:
string end;
};
void foo()
{
Trace t("Begin foo()", "End foo()");
cout<<"Do something in function foo()."<<endl;
}
int main()
{
foo();
return 0;
}
下面是程序的输出:
这样我们就可以向构造函数传递与函数名相关的参数信息了。这个Trace类应该很接近于实用了,可是当我们使用的过程中会发现这个类会存在几个问题:
1. 打印的信息有很多共同点,不利于我们查看,比如都以Begin开始,End结束等,有人也许不明白,打印的信息由我们传递给Trace构造函数的参数来决定,但是试想以下
我们有很多个函数,我们不太可能在每个函数中给Trace对象传递差异很大的字符串,这就像C++为什么要引入namespace来解决命名冲突的问题。
2. 众所周知,程序分为Release版和Debug版本