C++学习总结2

个人学习总结整理:

1、头文件包含两点原则
第一个原则
    如果可以不包含头文件,那就不要包含了,这时候前置声明可以解决问题。如果使用的仅仅是一个类的指针,没有使用这个类的具体对象(非指针),也没有访问到类的具体成员,
那么前置声明就可以了。因为指针这一数据类型的大小是特定的,编译器可以获知。
第二个原则
    尽量在CPP文件中包含头文件,而非在头文件中。假设类A的一个成员是是一个指向类B的指针,在类A的头文件中使用类B的前置声明即可。如果在A的实现中(.cpp)我们需要访问B的具体成员,
因此需要包含头文件,那么我们应该在类A的实现部分(CPP文件)包含类B的头文件而非声明部分(H 文件)(代码中实际是这样做的)。同理,命名空间的声明也应该尽量放在CPP文件中

2、单例模式
    说到单例模式,大家的第一反应应该是——什么是单例模式。单例模式的定义,官方的定义总结起来就两句话,!!确保一个类只有一个实例(也就是类的对象),
 并且提供一个全局的访问点(外部通过这个访问点来访问该类的唯一实例)。单例模式的实现其实只有两行代码,定义里面的这两句话分别对应一句代码。
    我们用代码来说话。我在这里新建一个控制台应用程序来给大家介绍单例模式。看到这里大家应该能明白,单例模式的实现代码了吧。

namespace _01单例模式
{
    class Program
    {
        static void Main(string[] args)
        {
            //我们在外部通过全局访问点去访问该类的唯一实例
            Singleton s = Singleton.only;
        }
    }
    public class Singleton//单例类
    {
        //2.提供一个全局访问点(其实就是一个全局静态字段),外部可以通过该字段访问该类的唯一实例
        //因为静态字段是属于类的,所以这样可以保证只有一个实例。
        public static Singleton only = new Singleton();
        //1 将构造函数声明成私有的,这样可以确保在类的外部无法实例化该类(即在类的外部获取不到类的实例)
        private Singleton() 
        {
        }
    }
}

第一步:[将类的构造函数生命为私有的构造函数],这样我们在外部就无法通过Singleton s = new Singleton()来实例化该,因为Private生命的成员只有在该类的内部可以访问。
       这样可以保证类的实例只有一个(那就是在类的内部给它实例化)。
第二步:[在类的里面声明一个公开的全局的静态字段(其实也就是提供一个全局的访问点),外部对象通过这个访问点可以拿到该类的唯一实例]。切记,该字段必须声明成static静态段,
       如果声明成非静态字段,那在类的外部就访问不到了。因为非静态成员只能通过类的实例去访问,而我们在类的外部是无法对该类进行实例化的。
注:  接下来的就是第二个问题,单例模式的作用是什么呢?其实定义单例模式的定义已经给了我们答案,作用就是————使得类的一个对象成为系统中的唯一实例。说了好像和没说一样吧,
  举个例子你就知道他有什么好处了。一个操作系统中可以存在多个打印任务,但我们只有一个打印机,同一时间只能有一个正在工作的任务,这个时候内存中打印机的这个类就必须是单例的,
  否则的话就可以同时执行多个打印任务,这显然会造成错误。

template<typename T>
struct Singleton
{
    static T& getInstance()
    {
        static T instance;
        return instance;
    }

    DISALLOW_COPY_AND_ASSIGN(Singleton)

protected:
    Singleton() {}
};

#define DEF_SINGLETON(object) struct object : Singleton<object>

3、命名规范:
3.1 采用驼峰命名 ,如:   getUrl、orgID
注意:
缩写为两个字母时,全部大写
常量名全大写,如:EMP_ID
魔法数字、字符统一提取,用常量
3.2 方法名、变量名有意义,如:
    String params = ht.get(Constatnt.MSB_INTERFACE_PARAMS); // 此处为MSB微服务调用入参
    String i = "1033";//
3.3 接口地址,全部小写,如:
       /srv/usercenter

4、函数对象
4.1 bool operator()  //提供一个本类型到bool的隐式转换,不允许使用参数
4.2 例:

struct ShouldRollBackSts
{
    bool operator()(const TransactionInfo& trans)  //为类类型的对象重载函数调用操作符
    {
        TRANS_TO_ROLE_BOOL(StState, state);
        return (state)->shouldRelease();
    }
};

5、const对象是不可以调用类中的非const成员函数
解析:

class test{
   int i;
 public:
   void print();
   test(int i);
};
test obj1(12);
obj1.print(); //ok
如果用test类创建一个const对象,然后去调用print()函数呢?这就会出现问题
const test obj2(122);
obj2.print();
###这时obj2对象的指针就会传递给test *this 指针,而obj2的地址翻译成指针类型应该是这样的,const test* this,即这时会出现类型不匹配的错误!!(不能将const指针转换为非const指针)

6、printf(",0x%02x",req[i]);
%02x : 表示以16进制的格式输出整数类型的数值,输出域宽为2,右对齐,不足的用字符0替代
       ( 前边的0x直接输出,后面的%02x是输出十六进制的数,保留两位有效数字)

7、 operator 重载

Status F1CtxtRelCmdReportAction::exec(const TransactionInfo& trans)
{
    BYTE counter;
    TRANS_TO_ROLE(UeCtxtRelCause, cause);
    if((cause->getTriggerMs() == ReleaseTrigger_Pps)&&(cause->operator unsigned int() ==  lucm_if::PpsTransmissionMessage_ErrorCause_rlf) //显示调用operator转换函数
        || (cause->getTriggerMs() == ReleaseTrigger_Spa))
    {
        counter = UeCtxtRel_RLF;
    }
    else
    {
        counter = UeCtxtRel_Other;
    }

    F1UeCtxtRelStatReporter::report(trans, counter);

    return DCM_SUCCESS;
}
UeCtxtRelCause::operator Status() const    // typedef unsigned int   Status;   //转换函数 ***
{
    return toolCause.isPresent() ? toolCause->cause : DCM_SUCCESS;
}

8、[*******类的普通数据成员不能在定义体内初始化]
    C++中类的数据成员不管是不是私有的,都不能进行初始化。因为类就相当于一个数据的模板,是一种自定义组合的新数据类型,而不是一个变量。当程序声明一个类的时候,
事实上并没有为程序申请存储空间,只有用这个类定义一个类对象的时候,才申请空间。连空间都没有,当然不能像定义变量一样的初始化了。
(例外:当初始化式是一个常量表达式时,整型const static数据成员就可以在类的定义体内进行初始化)

若一定要在类内初始化静态成员,那么就必须满足如下条件才行:
1) 静态成员必须为字面值常量类型的constexpr。
    所谓的字面值类型就是通常遇到的:算术类型,引用,指针等。字面值常量类型就是const型的算术类型,引用,指针等。
    所谓的constexpr,就是常量表达式,指值不会改变且在编译过程中就能得到计算结果的表达式。比如字面值,或者用常量表达式初始化的const对象也是常量表达式。
    为了帮助用户检查自己声明/定义的变量的值是否为一个常量表达式,C++11新规定,允许将变量声明为constexpr类型,以便由编译器来进行验证变量是否为常量表达式。
2)给静态成员提供的初始值,必须为常量表达式。

9、gdb调试
9.1、gdb ftest 
9.2、(gdb) b DedicatedMsgTransferHandler.cpp:1061 //打断点
           b + 偏移量
           b 函数名

           info b  //查看断点
9.3、(gdb) run --gtest_filter=FtAttach.should_attach_succ_am_with_msg4_opt_on verbose // 跑ft
        run (r)
        执行源源代码中一行的命令 next(简称n)//执行时如果遇到函数调用,可能想执行到函数内部,这时用step(简称p)
        continue(c) / continue + n 忽略指定次数的断点
        delete(d) d+编号  //删除断点或监视点    
9.4、(gdb) p/x *dirTransMsg  //打印
   p argv
   p *argv
   p argv[0] // 首元素指针
   p argv[1]

   p/格式 变量
     格式  x  显示为16进制
          d 显示为10进制
          u  无符号10进制数
          c 显示为字符 ASCII
          f 显示为浮点小树
          a  地址
9.5******[监视点]!!!
watch <表达式> //表达式发生变化时暂停
awatch <表达式> //表达式被访问、改变时暂停
rwatch <表达式> // 被访问时暂停
9.6*******
set $s= drbContext.qosFlow.size()
9.7 bt 查看调用堆栈  breaktrace

10、//ecplise 打开工程
****/ft/uc/project/setting.xml 
**[UCM代码转换成 C++Project ] 右键选择工程  new/other/ (C/C++) / Convert to a C/C++ Project (add C/C++ nature)

11、std::to_string(cpfUeId).c_str()   to_string使用

12、error: passing 'const HasPtr' as 'this' argument of 'const string HasPtr::getPs()' discards qualifiers [-fpermissive]|
常见原因:常量引用不能够调用非常量成员函数。

13、C++ override关键字 // 关键字and 保留字
描述:override保留字表示当前函数重写了基类的虚函数。
目的:1.在函数比较多的情况下可以提示读者某个函数重写了基类虚函数(表示这个虚函数是从基类继承,不是派生类自己定义的);2.强制编译器检查某个函数是否重写基类虚函数,如果没有则报错。
用法:在类的成员函数参数列表后面添加该关键字既可。

注意:override只是C++保留字,不是关键字,这意味着只有在正确的使用位置,oerride才启“关键字”的作用,其他地方可以作为标志符(如:int override;是合法的)

final关键字:
final关键字来限制类不能被继承,或者虚函数不能被重写
class A final 
{
    virtual void hehe() final;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值