小白的c++代码学习笔记
-
c++代码总结
1.构造,析构函数显式写出
构造,析构函数在hpp文件里声明后,有时不会自动生成,一定要在cpp文件中显式写出
Account::Account() { } Account::~Account() { }
2.c++function函数
void registerNotification(const std::string &name, const std::function<void(std::map<std::string, std::string>)> &handler);
此时要传入的第二个参数应该为一个 返回值为空,形参为一个map的参数 的函数,且只传函数名。
function<>()类似于一个指向函数的指针。3.时间戳变量time_t本质是一个长整形变量
time_t m_lastAccessTime = 0; writer.Uint64(m_lastAccessTime);
4.string是一个类,string变量不能初始化为NULL也和NULL比较
std::string m_id = "";
初始化
if (account.getId().size() != 0)
检查是否为空
5.enum声明和使用
enum EmailType { EmailTypeExchange = 1<<1, EmailTypeImap = 1<<2, EmailTypePop3 = 1<<3 };
Session Mailservices::buildSession(int emailType) { Session session; switch((EmaileType)emailType) { case EmailTypeExchange: session = ExchangeSession(); break; case EmailTypeImap: session = IMAPSession(); break; case EmailTypePop3: session = POPSession(); break; default: break; } return session; }
enum可以和int相互转换
6.const 修饰函数本身,函数参数和函数返回值
bool AccountManager::sameAccount(const std::shared_ptr<Account> accountA, const std::shared_ptr<Account> accountB) const {
前两个const修饰参数,可以防止传进函数的指针或引用的值在函数中被改变。但如果是按值传递,就不需要const修饰了。
最后一个const修饰该成员函数,任何不会修改数据成员的函数都应该声明为const 类型。如果在编写const 成员函数时,不慎修改了数据成员,或者调用了其它非const 成员函数,编译器将指出错误,这无疑会提高程序的健壮性。const char * GetString(void);
这个const修饰函数返回值,如果给以“指针传递”方式的函数返回值加const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
7.单例的声明和使用(方式之一)
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例
class KefuStatusManager { public: ~KefuStatusManager(); static KefuStatusManager* GetManager(); private: KefuStatusManager(); public: int SetKefuStatus(const KefuStatusManage::SetKefuStatusReq & objReq); int GetAllKefuStatus(KefuStatusManage::GetAllKefuStatusResp & objResp); private: std::mutex m_mutex_GetStatusCache; std::map<unsigned int, ::KefuStatusManage::kefuStatus >GetStatusID2Info; };
头文件中
KefuStatusManager * KefuStatusManager::GetManager() { static std::unique_ptr<KefuStatusManager> instance; static once_flag once; call_once(once, [&]() { instance.reset(new KefuStatusManager); }); return instance.get(); }
源文件中
KefuStatusManager::GetManager()->SetKefuStatus(objReq);
使用时
8.保留字override
override 仅在成员函数声明之后使用时才是区分上下文的,且具有特殊含义;否则,它不是保留的关键字。
使用 override 有助于防止代码中出现意外的继承行为。
父类中声明时,operationFinished 为虚函数class MAILCORE_EXPORT OperationCallback { public: virtual ~OperationCallback() { } virtual void operationFinished(Operation * op) {} }; }
cpp中子类实现时,operationFinished后面加了override关键字
class AsyncFolderSyncCallback : public OperationCallback { public: AsyncFolderSyncCallback() } ~AsyncFolderSyncCallback() { } void operationFinished(Operation *op) override {}//没写函数里面的内容
9.c++储存信息与json语句相互转化 -- rapidjson库
rapidjson中文文档
c++转json:StringBuffer jsonString;//用于接收生成的json语句 Writer<StringBuffer> writer(jsonString); writer.StartObject(); //开始 writer.Key(F_ACC_ID); writer.String(m_id.c_str()); writer.Key(F_ACC_EMAIL_TYPE); writer.Int(m_emailType); writer.Key(F_ACC_LAST_ACCESS_TIME); writer.Uint64(m_lastAccessTime); //不同的数据类型调用不同的方法,string类型要转成char* writer.EndObject(); //结束 std::string jsonToString = jsonString.GetString();//将StringBuffer类转换成string
json转c++:
rapidjson::Document document; document.Parse(json.c_str());//json是json格式的string实例 if (document.HasParseError()) { rapidjson::ParseErrorCode code = document.GetParseError();//如果解析错误则获取错误码 SE_LOG_DEBUG(kMailModule, "parse json error %d, but not necessary", code);//将错误码返回上层,与rapidjson无关 return; } mailAddress.displayName = document[F_JSON_DB_MAIL_DISPLAYNAME].GetString(); mailAddress.mailBox = document[F_JSON_DB_MAIL_MAILBOX].GetString(); //取出自己想要的值
-
为啥头文件里声明的构造函数有时不会自动生成?
-
@tangbin
只在下面四种情况的时候编译器会自动生成默认构造函数
1、 如果类A成员中含有某个类B的对象,恰好类B也显示定义了构造函数,那么在产生类A对象的时候编译器会产生一个默认构造函数,在这个默认构造函数中提供了调用类A构造函数的代码。
2、如果类B继承于类A,且类A显示定义了构造函数,那么在生成类B对象的过程中编译器同样会产生一个默认构造函数,在这个构造函数中提供调用基类A构造函数的代码。
3、如果某个类含有虚函数,那么编译器会自动产生一个默认构造函数以提供虚表指针相关的初始化操作
4、如果一个类虚继承于其他类,那么同样的编译器会为该类产生默认的构造函数。
并不是随时都会生成。
-
所以是不是可以理解为 只有当类A继承或含有一个有构造函数的类B的时候,才会自动生成构造函数
-
我觉得枚举本身应该就是整形吧.但是整形并不是枚举类型.
-
@young
嗯 但int类型的变量也可以当成某个枚举来用啊
-
@zhijun
准确说是需要生成构造函数的时候才会自动生成