• C++是一个语言联邦(Federation of languages)函数
1. C Style languagethis
2. Object-Oriented C++spa
3. Template C++指针
4. STL/TR1/boost..代码规范
• 使用const,enum,inline代替#definecode
1. 使用const datatype constName = constValue 代替 #define constName constValue对象
好比全局常量:blog
const int maxN = 1000005; //代替 #define maxN 1000005
在类中,类专属常量:编译器
class someClass{ private: static const int maxN = 1000005; int someData[maxN]; ... }
2. enum hack!string
class someClass{ private: enum { maxN = 1000005 };//enum令maxN变成一个记号名称 int someData[maxN]; ... }
enum的某些特性更像#define而不是const,某些状况下更符合咱们的需求。(例如取地址对于enum不合法而对const就合法)
enum hack使template metaproprogramming的基础技术。
3. 使用inline function代替宏
常见宏 #define call_with_max(a, b) foo(a > b ? a : b) 会出现大量的错误,
必须使用小括号将参数所有区别 #define call_with_max(a, b) foo((a) > (b) ? (a) : (b)) ,
即使如此在实际操做时依旧容易出错(不能扩展代码与灵活调用),应用inline function取代
template <typename T> inline void callWithMax(const T& a, const T& b){ foo(a > b ? a : b); }
• Const的妙用
1. Const声明帮助编译器侦测出错误
const指定了一个不可改动的对象,而编译器会强制的实施它。(!指出来能够得到编译器的帮助,确保其不被违反!)
这个对象能够是global或者namespace域中的常量。也能够修饰block scope中被声明为static的对象,亦能够修饰class内部的全部变量。
而对于指针,能够指出指针自身,指针所指,二者皆是,或二者皆不是Const。在*左表示指针所指是常量,在*右表示指针自身是常量,而在*两侧表示二者皆是常量。
int someValue = 12345; int* pSomeValue = someValue; // 二者皆不是常量 const int* pSomeValue = someValue // 所指为常量 int* const pSomeValue = someValue // 指针为常量 const int* const pSomeValue = someValue // 二者皆是常量
void foo(const dataType* arg) // 传入一个指向常量的指针 void foo(dataType const* arg) // 与上面相同 在*左次序颠倒没有区别
迭代器也是指针衍生出来的,因此
std::vector<int> vec; ... const std::vector<int>::iterator iter = vec.begin(); // 迭代器的做用就像一个 T* const (模板变量的常量指针) *iter = 12345; // ok! 指针所指不是常量 ++iter; // error! 指针自己是常量 std::vector<int>::const_iterator cIter = vec.begin(); // cIter的做用如同一个 const T* (模板常量的变量指针) *cIter = 12345; // error! 指针所指是常量 ++cIter; // ok! 指针自己不是常量
将const应用于函数声明
良定义的数据类型应尽可能避免隐式类型转换,这时返回一个常量值就十分有用
class Rational {...}; const Rational operator+ (const Rational& lhs, const Rational rhs); const Rational operator* (const Rational& lhs, const Rational rhs); ...
这样定义, if(a * b = c) // 本意是想作一个if(a * b == c)的比较 这样的错误就不会出现,而会被编译器直接警告。
2. const成员函数
使用const来控制成员函数对对象的可读写性是很重要的,由于这样可使class借口更容易被理解,而且还可使操做const对象成为可能。这对高效编写代码很重要。
class SomeText { public: ... const char& operator[](std::size_t position) const { return text[position]; } char& operator[](std::size_t position) { return text[position]; } } SomeText text("Hello,world!"); std::cout << text[0]; // 调用non-const方法 能够读 text[0] = 'A'; // 调用non-const方法 能够写 const SomeText cText("Hello,world!"); std::cout << cText[0]; // 调用const方法 能够读 cText[0] = 'A'; // 调用const方法 不可写!
对于在const中也想改变的量,使用mutable能够声明在const成员函数内依旧可被更改的变量。
若是成员函数代码功能相同而只有常量变量的区别,能够const_cast,static_cast来避免代码重复。
class SomeText { public: ... const char& operator[](std::size_t position) const { ... ... ... return text[position]; } char& operator[](std::size_t position) { return const_cast<char&> // 移除返回值的const (static_cast<const SomeText&> // 为*this加上const (*this)[position]); // 调用const op[] }
• 变量与对象的初始化与代码规范
1. 代码规范:
类型 | 规范 | 示例 |
简单数据类型 | 首字母小写表示类型,以后按单词分割每单词首字母大写。 |
int iMaxNum = 10000; char cRank = 'A'; string sName = "LevisonChen"; double dSpeed = 1.357; int* pMaxNum = iMaxNum; |
复杂数据类型 | 首字母小写,首词表示数据类型,以后按单词分割每单词首字母大写 |
std::vector<int> vecEdges;
|
函数 | 按单词分割每单词首字母大写 |
void Foo(){ ... } int GetMaxinum(std::vector<int> vecArg){ ... } |
类与结构体 | 按单词分割每单词首字母大写,私有字段不使用首词表示数据类型 |
class SomeClass { ... } struct SomeStruct { ... } |
缩进 | tab-4spaces缩进 |
{
...
{
...
{
...
...
...
}
...
}
...
}
|
2. 不要混淆赋值(assignment)和初始化(initialization)
class Person { public: Person(const std::string& sName, const std::int& iAge, const std::list<PhoneNumber>& listPhones, const std::list<EmailAddress>& listEmails); private: std::string name; std::int age; std::list<PhoneNumber> phones; std::list<EmailAddress> emails; }; Person::Person(const std::string& sName, const std::int& iAge, const std::list<PhoneNumber>& listPhones, const std::list<EmailAddress>& listEmails) { name = sName; age = iAge; phones = listPhones; emails = listEmails; } // 这是赋值而非初始化!
Person::Person(const std::string& sName, const std::int& iAge, const std::list<PhoneNumber>& listPhones, const std::list<EmailAddress>& listEmails) :name(sName), age(iAge), phones(listPhones), emails(listEmails) // 这是初始化! {}
为了消除跨编译时的单元初始化次序问题,应以local static对象替换non-local static对象。