WebRTC源码分析之定位-Location


Location类用于记录类对象产生的位置信息,方便日志的打印。记录的信息主要有,类对象产生的 文件名、所在的 函数名、所在文件的 行号

Location使用示例
工程

示例工程:https://pan.baidu.com/s/1rbI2hwXpMA-Pb-i-zCdVWA 提取码:cenz

示例
#include <iostream>
#include "location.h"

using namespace std;

class A
{
public:
    A(rtc::Location l)
        :lt_(l)   
    {}

    void displayLocation()
    {
        /*获取位置信息*/
        cout << lt_.ToString() << endl;
    }

private:
    rtc::Location lt_;       /*记录类A对象产生的位置*/
};

A* func()
{
    return new A(RTC_FROM_HERE);   /*定义类A对象时,记录产生的位置。*/
}

int main()
{
    A* pa = func();

    pa->displayLocation();

    return 0;
}

在这里插入图片描述
在这里插入图片描述

运行结果分析如上图,记录了类A对象产生时,所在的函数名、文件名及行号。

Location源码分析
实现原理

通过编译器提供的宏记录类对象产生的位置信息。主要的宏有如下三个:

__FUNCTION__:记录这个宏所在的函数名

__FILE__:记录这个宏所在文件名

__LINE__:记录这个宏所在的行号

使用示例如下:

#include <iostream>

using namespace std;

void func()
{
	cout << "__FUNCTION__ = " << __FUNCTION__ << endl;
	cout << "__FILE__     = " << __FILE__ << endl;
	cout << "__LINE__     = " << __LINE__ << endl;
}

int main()
{
	func();

	return 0;
}

在这里插入图片描述

类的声明
class Location 
{
 public:
  Location(const char* function_name, const char* file_and_line);  
  Location();
  Location(const Location& other);
  Location& operator=(const Location& other);

  const char* function_name() const { return function_name_; }
  const char* file_and_line() const { return file_and_line_; }

  std::string ToString() const;

 private:
  /*存储着对象在哪个函数中产生*/
  const char* function_name_;   
    
  /*存储着对象在哪个文件的哪一行代码中产生*/
  const char* file_and_line_;   
};
构造器和赋值运算符重载
/*有参构造器*/
Location::Location(const char* function_name, const char* file_and_line)
    : function_name_(function_name), file_and_line_(file_and_line) {}

/*无参构造器*/
Location::Location() 
    : function_name_("Unknown"), file_and_line_("Unknown") {}

/*拷贝构造器*/
Location::Location(const Location& other)
    : function_name_(other.function_name_),
      file_and_line_(other.file_and_line_) {}

/*赋值运算符重载*/
Location& Location::operator=(const Location& other) 
{
  function_name_ = other.function_name_;
  file_and_line_ = other.file_and_line_;
    
  return *this;
}

这些代码没有什么难点,就不要解释了。

将位置信息转成字符串
std::string Location::ToString() const 
{
  char buf[256];
  snprintf(buf, sizeof(buf), "%s@%s", function_name_, file_and_line_);
  return buf;
}

通过ToString()函数可以将类的位置信息转成字符串并返回。

RTC_FROM_HERE宏

为了方便使用和明确语义,WebRTC定义了RTC_FROM_HERE宏,这个宏的作用是定义一个Location类对象。

#define RTC_FROM_HERE RTC_FROM_HERE_WITH_FUNCTION(__FUNCTION__)

#define RTC_FROM_HERE_WITH_FUNCTION(function_name) \
  ::rtc::Location(function_name, __FILE__ ":" STRINGIZE(__LINE__))

将这两个宏展开后的结果是:

::rtc::Location(__FUNCTION__, __FILE__ ":" STRINGIZE(__LINE__))

关于STRINGIZE宏,是宏使用中的一个技巧。分析如下:

在C语言和C++中,多个字符串连在一起,可以看成一个字符串。

char buf[] = "China" " is" " great";
cout << buf << endl;

运行结果是:China is great

#define str(x)  "x"
cout << str(123) << endl;

运行结果是:x

#define str(x)  x
cout << str(123) << endl;

运行结果是:123

#define str(x)  "aaa"x"bbb"
cout << str(123) << endl;

运行出错

#define str(x)  "aaa"#x"bbb"
cout << str(123) << endl;

运行结果是:aaa123bbb

在宏函数中#可以将参数字符串化,"aaa"#x"bbb"经宏替换后为"aaa""123""bbb",也就等价于"aaa123bbb"

会到待分析的码中,STRINGIZE(__LINE__)宏展开过程如下:

#define STRINGIZE_NO_EXPANSION(x) #x
#define STRINGIZE(x) STRINGIZE_NO_EXPANSION(x)

展开后的结果为:

#__LINE__

把所有的宏展开以后结果为:

::rtc::Location(__FUNCTION__, __FILE__ ":" "__LINE__")

之所以大费周折的使用STRINGIZE宏,是因为__FILE__是字符串,而__LINE__是整数,为了将它们连接成字符串,需要将__LINE__字符化,字符化后再连接成字符串。

小结

本文分析了Location类的实现方式,主要分析了编译器提供的宏和一些宏使用的技巧。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值