当前位置: 首页 > news >正文

网络公司网站设计方案ppt又拍云 wordpress使用

网络公司网站设计方案ppt,又拍云 wordpress使用,网站建设行业标准,手机百度网页版主页最近写了一些博客复习C的知识#xff0c;但理论终究是理论#xff0c;那多态、继承等C特性到底该在什么情况下使用#xff1f;如何模块化地完成一个程序呢#xff1f;还有没有什么C语法方面值得学习的知识呢#xff1f;本节就来分析一个实际项目中的例子#xff0c;来理解…最近写了一些博客复习C的知识但理论终究是理论那多态、继承等C特性到底该在什么情况下使用如何模块化地完成一个程序呢还有没有什么C语法方面值得学习的知识呢本节就来分析一个实际项目中的例子来理解这些知识和用法。 我们写程序的过程中难免会用到输出比如输出到控制台输出到串口或者输出一些调试信息到文件系统。那么我们应该怎样设计一个类可以支持输出到不同的地方呢这节课就来简单地分析一个用于输出的类应该如何实现。本节例子的源码摘自NXP官方用于加密镜像的开源C项目elftosb。 参考elftosb源码 文章目录 1 代码分析1.1 main1.2 输出类分析Log、Logger和StdoutLogger类1.3 smart_array_ptr类 2 总结2.1 输出类实现总结2.2 C知识总结 1 代码分析 1.1 main 一个程序从main开始运行首先看一下main函数 int main(int argc, char *argv[], char *envp[]) {try{return elftosbTool(argc, argv).run();}catch (...)//...表示捕获所有异常{Log::log(Logger::ERROR, error: unexpected exception\n);return 1;}return 0; }可以看到程序就是通过接收命令行参数构造一个elftosbTool类然后调用类方法run()来运行。同时这里使用了异常机制来捕获所有异常。下面先来分析一下出现的Log类。 1.2 输出类分析Log、Logger和StdoutLogger类 Log类中有调用Logger类所以一起来看看这两个**类声明** class Logger { public:enum log_level_t //log等级{URGENT 0, //! The lowest level, for messages that must always be logged.ERROR, //! For fatal error messages.WARNING, //! For non-fatal warning messages.INFO, //! The normal log level, for status messages.INFO2, //! For verbose status messages.DEBUG, //! For internal reporting.DEBUG2 //! Highest log level; verbose debug logging.};public:Logger(): m_filter(INFO), m_level(INFO){}//构造函数virtual ~Logger() {}//析构函数inline void setFilterLevel(log_level_t level) { m_filter level; }//设置过滤等级inline log_level_t getFilterLevel() const { return m_filter; }//获得过滤等级inline void setOutputLevel(log_level_t level) { m_level level; }//设置输出等级inline log_level_t getOutputLevel() const { return m_level; }//获得输出等级/* 几种不同格式的输出,虚函数 */virtual void log(const char *fmt, ...);virtual void log(const std::string msg) { log(msg.c_str()); }virtual void log(log_level_t level, const char *fmt, ...);virtual void log(log_level_t level, const std::string msg) { log(level, msg.c_str()); }virtual void log(const char *fmt, va_list args);virtual void log(log_level_t level, const char *fmt, va_list args);protected:log_level_t m_filter; //过滤等级log_level_t m_level; //输出等级protected:virtual void _log(const char *msg) 0; };class Log { public:static inline Logger *getLogger() { return s_logger; } //返回Logger对象static inline void setLogger(Logger *logger) { s_logger logger; } //设置Logger对象/* Log类继承了Logger中其中四种输出虚函数 */static void log(const char *fmt, ...);static void log(const std::string msg);static void log(Logger::log_level_t level, const char *fmt, ...);static void log(Logger::log_level_t level, const std::string msg);protected:static Logger *s_logger; //全局loggerpublic:/* SetOutputLevel类 */class SetOutputLevel{public:/* 设置输出等级的两个重载函数:用全局的s_logger输出 */SetOutputLevel(Logger::log_level_t level): m_logger(Log::getLogger()),m_saved(Logger::INFO){assert(m_logger);m_saved m_logger-getOutputLevel();m_logger-setOutputLevel(level);}/* 传入一个创建的logger类输出 */SetOutputLevel(Logger *logger, Logger::log_level_t level): m_logger(logger), m_saved(logger-getOutputLevel()){assert(m_logger);m_logger-setOutputLevel(level);}/* 恢复当前的Logger输出类为全局的s_logger,输出等级是之前设置的 */~SetOutputLevel() { m_logger-setOutputLevel(m_saved); }protected:Logger *m_logger; //指向当前类的Logger输出类Logger::log_level_t m_saved; //这里还保存了原来的输出等级}; };上面类的声明很好理解我们可以从中学到一些细节 (1)基类析构函数加virtual 不加的话当基类销毁时不会调用派生类的析构函数反之会先调用派生类的析构函数再调用基类的析构函数 (2)类函数中的inline 其实在类内实现的函数默认就为内联函数这里加上inline是确保其为内联函数或确保在不同编译器都为内联(可能有的编译器不会默认内联?)。 (3)类函数中的static 所有声明该类的变量共用此方法。 (4)类中声明类 上面的Log中的public下还声明了一个SetOutputLevel类实际上在Log类各个方法的实现中并没有任何方法调用到这个类。这样做可以让代码的逻辑更清晰也完成了特定的需求功能首先整个Log类顾名思义作用就是输出所以方法里应该要有输出函数和设置输出等级对于输出等级来说这里单独封装了一个SetOutputLevel类用于设置logger的输出等级。 注意这里的析构函数~SetOutputLevel()恢复了之前的输出等级也就是说加入默认的输出等级是INFO在某个方法中的输出等级需要为URGENT我们可以声明一个SetOutputLevel局部变量改变仅此方法输出的输出等级为URGENT在此方法调用完后析构函数将恢复为之前的输出等级INFO而不需要用户自行恢复。 Logger类的实现 Log就是通过s_logger调用方法实际上也是调用Logger类这里就不贴Log类的代码了。在Logger中所有的log重载函数经过格式转换后最后调用的都是Logger::log(log_level_t level, const char *fmt, va_list args) void Logger::log(log_level_t level, const char *fmt, va_list args) {smart_array_ptrchar buffer new char[1024];vsprintf(buffer, fmt, args);if (level m_filter){_log(buffer);} } 可以看到最终都是调用_log函数对接输出接口进行输出。 用户自定义输出类 因为Logger中的virtual void _log(const char *msg)为虚函数所以用户只需要声明一个输出接口类并继承Logger类然后重写_log实现自己的输出方法即可。如这里代码中实现了std标准输出类 class StdoutLogger : public Logger { protected:virtual void _log(const char *msg); };void StdoutLogger::_log(const char *msg) {printf(%s, msg); }同理假设想输出到串口用户只需定义一个串口输出类继承Logger即可。 实际使用流程 现在回到main函数在catch中直接使用Log::log()进行输出异常提示信息说明已经有地方调用Log类的类方法setLogger设置了s_logger并且这个s_logger也实现了_log虚函数。 再来看在try的代码块中执行了return elftosbTool(argc, argv).run()所以我们来看一下elftosbTool类及其的构造函数(此类为整个程序的主类,有很多变量和方法实现,这里仅展示与输出类有关的部分) class elftosbTool { protected:int m_argc; //! Number of command line arguments.char **m_argv; //! String value for each command line argument.StdoutLogger *m_logger; //! Singleton logger instance.public:elftosbTool(int argc, char *argv[]): m_argc(argc), m_argv(argv), m_logger(0){m_logger new StdoutLogger();m_logger-setFilterLevel(Logger::INFO);Log::setLogger(m_logger);} }可以看出elftosbTool使用标准输出所以声明了StdoutLogger *m_logger变量。在构造函数中分配了一个StdoutLogger对象并设置默认输出等级为INFO。然后设置Log中的默认全局输出变量static Logger *s_logger为m_logger。这样用户只需调用Log类进行输出即可同时可以更改输出的等级假设有一个printInfo函数 void printInfo() {Log::SetOutputLevel leveler(Logger::DEBUG);Log::log(positional args:\n); }1.3 smart_array_ptr类 我们注意到前面的Logger::log类实现中有一行smart_array_ptrchar buffer new char[1024]还用到了一个smart_array_ptr类。这个类是一个智能指针它封装了对动态数组的内存管理并且提供了一些方便的运算符重载。下面来看一下这个类的声明 template typename T class smart_array_ptr { public:typedef T data_type;typedef T *ptr_type;typedef const T *const_ptr_type;typedef T ref_type;typedef const T const_ref_type;smart_array_ptr(): _p(0){}smart_array_ptr(ptr_type p): _p(p){}virtual ~smart_array_ptr() { safe_delete(); }ptr_type get() { return _p; }const_ptr_type get() const { return _p; }/* 设置数组指针,并释放前一个指针的内存 */void set(ptr_type p){if (_p p ! _p){safe_delete();}_p p;}void reset() { _p 0; }void clear() { safe_delete(); }/* 释放分配的内存 */virtual void safe_delete(){if (_p){delete[] _p;_p 0;}}operator ptr_type() { return _p; }operator const_ptr_type() const { return _p; }operator ref_type() { return *_p; }operator const_ref_type() const { return *_p; }operator bool() const { return _p ! 0; }smart_array_ptrT operator(const_ptr_type p){set(const_castptr_type(p));return *this;}ptr_type operator-() { return _p; }const_ptr_type operator-() const { return _p; }ref_type operator[](unsigned index) { return _p[index]; }const_ref_type operator[](unsigned index) const { return _p[index]; }protected:ptr_type _p; };使用: smart_array_ptrchar buffer new char[1024]整体来说代码还是很好理解的但有一些C语法还是值得推敲的 1、两个构造函数调用的情况 (1)调用smart_array_ptr(ptr_type p): _p(p) smart_array_ptrchar buffer new char[1024];上面的代码由于是在声明时的赋值在C中等价于smart_array_ptrchar buffer(new char[1024])。 (2)调用smart_array_ptr():_p(0) smart_array_ptrchar buffer; buffer new char[1024];先调用无参构造函数然后再调用运算符的重载函数smart_array_ptrT operator(const_ptr_type p)。 2、重载函数分析 (1)operator 数据类型(){}该类的对象可以直接与特定数据类型的变量进行比较或赋值 typedef T data_type; typedef T *ptr_type; typedef const T *const_ptr_type; typedef T ref_type; typedef const T const_ref_type;operator ptr_type() { return _p; } operator const_ptr_type() const { return _p; } operator ref_type() { return *_p; } operator const_ref_type() const { return *_p; } operator bool() const { return _p ! 0; }调用例子 smart_array_ptrchar buffer1 new char[16]; const smart_array_ptrchar buffer2 new char[16];char *tmp1 buffer1; //调用operator ptr_type() const char * tmp2 buffer2; //调用operator const_ptr_type() const char tmp3 buffer1; //调用operator ref_type() const char tmp4 buffer2; //调用operator const_ref_type() const const bool tmp5 buffer2; //调用operator bool() const(2)返回值 operator重载运算符(参数){}重载类的运算符 ptr_type operator-() { return _p; } const_ptr_type operator-() const { return _p; } ref_type operator[](unsigned index) { return _p[index]; } const_ref_type operator[](unsigned index) const { return _p[index]; }调用例子 class test{ public:void test1(){printf(test\r\n);}void test2()const{printf(test\r\n);} };smart_array_ptrtest str1 new test[16]; const smart_array_ptrtest str2 new test[16]; smart_array_ptrchar buffer1 new char[16]; const smart_array_ptrchar buffer2 new char[16];str1.operator-()-test1(); //调用ptr_type operator-() str2.operator-()-test2(); //调用const_ptr_type operator-() const buffer1[0] 1; //调用ref_type operator[] const int a buffer2[0]; //const_ref_type operator[](unsigned index) const实际上重载-运算符并不常用这里仅仅是举一个例子 2 总结 2.1 输出类实现总结 本文介绍了elftosb工程中的输出类Log、Logger和StdoutLogger的实现我们来总结一下其中的原理 Logger类输出类中的底层最终将调用这个类方法进行输出它封装了一些格式化输出的函数同时留出一个虚函数接口_log即我们的输出方式有很多种如标准输出、串口输出和网络输出等。StdoutLogger类继承Logger类实现具体的_log输出方法这里实现的是标准输出Log类给用户实际调用输出的类其中声明了一个static Logger *s_logger变量用户可以使用类方法setLogger进行设置这个Logger 然后调用Log类中的log输出函数实际上就是调用s_logger的类方法。 同时这个类还提供了更改输出等级的类SetOutputLevel用于更改某个Logger 的输出等级 大家在设计类的时候可以学习一下这种模块化的设计。 2.2 C知识总结 (1)基类析构函数加virtual会先调用派生类的析构函数再调用基类的析构函数 (2)类函数中的inline在类中实现的方法默认内联加上是为了以防万一同时显式地让程序员知道这是内联函数 (3)类中的static对于类中变量后续创建该类的实例的时候不会重复创建这些变量的空间因为这是所有对象共享的变量对于类中的方法不需要类的对象就可以被调用它只能访问静态成员变量或其他静态类方法。 (4)类中声明类在本例中巧妙地运用了这个类中类的声明和析构函数的特性让用户可以在任意函数中设置一次输出等级然后在函数退出后调用析构函数恢复之前的输出等级 (5)运算符重载 operator 数据类型(){}该类的对象可以直接与特定数据类型的变量进行比较或赋值返回值 operator重载运算符(参数){}重载类的运算符
http://www.pierceye.com/news/786172/

相关文章:

  • 加工企业网站这么做常德网站建设企业
  • 百度举报网站wordpress主题缩略图
  • 南宁快速网站建设电话WordPress电影公司网站
  • 什么网站可以直接做word文档亚马逊周末可以视频认证吗
  • 网站设计申请书买购网官方网站
  • 深圳做网站建设公司青岛网景互联网站建设公司
  • 做公司网站要多少钱洛阳信息网
  • asp 网站名字免费的公众号排版工具
  • 郑州响应式建站查企业的信息在哪个官网
  • 大型企业网站开发怎么使用免费的wordpress
  • 大连做网站大公司建设项目咨询公司网站
  • 教育培训网站建设方案鞍山建设信息网站
  • 重庆网站建设哪家强平台如何做推广
  • 安徽省建设安全监督站的网站网站建设公司一般多少钱
  • 服装网站建设策划书3000字软件开发包含网站开发吗
  • 免费网站的建设绵阳网站建设制作
  • 学生处网站建设招标公告网站包括哪些主要内容
  • 成都门户网站建设多少钱聚合广告联盟
  • 坦克大战网站开发课程设计报告软文营销的本质
  • 美食网站开发网站登录验证码是怎么做的
  • 电子商务网站排名辽宁省建设工程信息网业绩公示
  • 天津建设科技杂志的官方网站wordpress cnzz插件
  • 滨州建设网站太原网站建设优化
  • 记事本做网站怎么改字体包装设计模板设计素材
  • 下载软件的网站推荐thinkphp和wordpress
  • 青海省城乡和住房建设厅网站合肥小吃培训网页设计
  • 财经门户网站建设django校园网站开发
  • 泉州网站建设报价广东建设厅网站
  • 建设网站的源代码的所有权wordpress网站打开慢
  • 印度外贸网站有哪些家居小程序源码下载