原文:http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Default_Arguments
Default argument的好處在於,你不必再為了一些罕見的special case而另外寫一個function,直接使用default argument即可。而且default argument和function overloading比起來,default argument可以用更清楚的方式來分區必要的(required)和非必要的(optional)引數。
Default argument的壞處在於,和function pointer一起使用時會出問題:
typedef void (*PFN)(int);
void Foo(int a = 10)
{
    cout << a << endl;
}
void main()
{
    PFN pfn = Foo;
    pfn();
}
以上程式在VS 2008會出現以下compile error:
error C2198: 'PFN' : too few arguments for call
所以當加入一個default argument到現有的function時,可能就會引發上述的compile error。(如果該function有透過function pointer來呼叫的話)
除此之外更動default argument會影響每一個呼叫該function的地方(call site),使用function overloading則沒有這個問題。
由於使用default argument的缺點大於優點,Google C++ Style Guide禁止使用default argument。必要時,你可以自行使用function overloading來模擬default argument。
以下是Google C++ Style Guide指出可以使用default argument的少數例外:
1. 當該function為static function時,此時上述的缺點將不存在。
2. 當透過default argument來模擬variable-length argument lists時:
// Support up to 4 params by using a default empty AlphaNum.
string StrCat(const AlphaNum &a,
    const AlphaNum &b = gEmptyAlphaNum,
    const AlphaNum &c = gEmptyAlphaNum,
    const AlphaNum &d = gEmptyAlphaNum);

coherence 發表在 痞客邦 留言(0) 人氣()

原文:http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Function_Overloading
C++允許function overloading(C語言不允許),可以讓多個functions擁有一樣的名字,只要這些functions的parameters或return type不同。比方說:
class MyClass {
public:
    void Analyze(const string& text);
    void Analyze(const char* text, size_t textlen);
};
Google C++ Style Guide規定,當你要使用function overloading時,必須先確定將來maintain這份code的人可以一眼就看出要使用哪個overload function。如果不能一眼看出的話,那就不要用function overloading。(例如:用AppendString和AppendInteger來取代Append)
Function overloading的好處在於可以解決函數命名的問題(若functions的功能相同,卻因傳入的parameters有些微的差異,就要另外想一個新的function name)。function overloading是template的基礎;function overloading也是visitor pattern所必須。
但function overloading的壞處在於,會讓maintain這份程式的人混淆到底要呼叫哪一個function。若在class繼承時,derived class沒有override base class全部的overload functions,也會讓人感到困惑。

coherence 發表在 痞客邦 留言(0) 人氣()

  • Mar 16 Sat 2013 22:37
  • sizeof

原文如下:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#sizeof
Google C++ Style Guide建議,盡量使用sizeof(varname),而非sizeof(type)。
比方說程式中有一個MyStruct;
struct MyStruct
{
    int a;
    int b;
};

coherence 發表在 痞客邦 留言(0) 人氣()

原文:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Interface
C++並沒有定義interface這個關鍵字(Java和C#有定義interface關鍵字),在C++中只要有class或struct(class和struct的功能幾乎相同)符合下列條件,我們就可以稱之為interface:
* 所有的method都為pure virtual method或static method
* 不能有任何的non-static data members
* 沒有定義任何ctor;如果有定義ctor的話,該ctor必須設為protected,並且不能有任何的parameter
* 如果它有繼承其他的classes,這些classes也都必須符合interface的條件
Google C++ Style Guide建議符合以上條件的class或struct,要採用以Interface作為後綴的naming rule,雖然這樣的後綴有點冗長(mircosoft的interface naming rule是以I作為前綴),但這樣的規定確保未來maintain程式碼時,一眼就可以看出哪些class或struct是interface。其實Google C++ Style Guide沒有強制規定一定要使用Interface後綴,但是如果你用了Interface作為class或struct的後綴,那該class或struct就必須符合上述的那些條件。
Interface classes不能直接instantiate,因為它們有pure virtual functions;通常會使用interface class是因為不希望client端知道時作的細節,所以這些interface classes的實作將會放在它們的subclass中,也因如此interface classes必須宣告virtual dtor確保subclass中的dtor會被呼叫,而沒有memory leak的風險。

coherence 發表在 痞客邦 留言(0) 人氣()

原文:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Copy_Constructors
C++中的class是value type by default(C#和Java中的class是reference type by default),在撰寫C++程式時,難免需要class instances之間的拷貝,Copy ctor和assignment operator就是用於這種場合。當你從一個現有的class instance來創建另一個class instance時,Copy ctor就會被呼叫。當你把一個現有的class instance用賦值給另一個class instance時,assignment operator就會被呼叫。copy ctor和assignment operator也常用於STL container之中。若沒有為class宣告copy ctor或assignment operator時,compiler會為你隱式生成。
其實只有少數的class有被拷貝的需求,而compiler隱式生成的copy ctor和assignment operator常是bug的根源,也會造成performance上的問題(和call-by-reference比起來),而且copy ctor和assignment operator會降低程式的可讀性,因為它們不像一般的function一樣,必須顯式的去呼叫它;所以你往往難以trace到底哪些地方呼叫了copy ctor或assignment operator。所以Google C++ Style Guide規定只有當你有拷貝需求時才去實作copy ctor和assignment operator,若沒有這樣的需求;則必須使用goole自定義的macro DISALLOW_COPY_AND_ASSIGN來防止compiler隱式產生copy ctor和assignment operator,而DISALLOW_COPY_AND_ASSIGN不過就是copy ctor和assignment operator的宣告,你必須把它放在private access level裡面。
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
    TypeName(const TypeName&);             \
    void operator=(const TypeName&)
把該macro用於class CFoo:
class CFoo {
public:
    CFoo(int f);
    ~CFoo();
private:
    DISALLOW_COPY_AND_ASSIGN(CFoo);
};
使用DISALLOW_COPY_AND_ASSIGN時切記不要提供copy ctor和assignment operator的定義,如此一來拷貝CFoo時就會出現link error。
也因為class instances之間的拷貝有這些問題,所以Google C++ Style Guide也建議,如果你有performance上的考量,可以使用call-by-reference來取代call-by-value,或是將class的pointer存於STL container而非class的instance。你也可以自己定義拷貝函數(CopyFrom()或Clone()),並將class instance的拷貝實作於此,來避免可讀性上的問題(Java的object有提供拷貝函數clone())。當然如果你的class有用於STL container的需求,還是要自定義copy ctor和assignment operator。

coherence 發表在 痞客邦 留言(0) 人氣()

原文:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Declaration_Order
在一個class中,規定declaration的順序為public → protected → private。這樣的規定通常是為了程式的可讀性,把越重要的部份擺在越前面,一個class的interface(廣義的interface)就是它與外界溝通的那些public member functions,所以將public section放在最前面,而只有該class內部會用到的data member或help functions自然就設為private並且放在最後面。
而在每一個section當中,Google C++ Style Guide規定宣告的順序為:
1. Typedefs and Enums
2. Constants (static const data members)
3. Constructors
4. Destructor
5. Methods, including static methods
6. Data Members (except static const data members)

coherence 發表在 痞客邦 留言(0) 人氣()

原文:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Access_Control
一個class與外界溝通的interface(廣義的interface)就是它的public member functions;而呼叫這些public member functions的地方我們可以稱之為client。當設計一個class時,重要的是該class的interface要完整且不要有多餘的public member functions,client用不到的member function就要將之設為private,以避免外界的接觸。
這麼作的原因是在於,減少外界的接觸就等於降低該class與client之間的耦合,將來該class需要改變時,也不需要修改太多client的程式。

coherence 發表在 痞客邦 留言(0) 人氣()

原文:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Default_Constructors
若你的class沒有定義ctor時,compiler會自動隱式生成一個default ctor給你;當你的class中有定義data members時,compiler隱式生成的default ctor並不會給予你的data members適當的初值。
class Cls
{
public:
    int GetData() const
    {
        return m_nData;
    }
    double GetDouble() const
    {
        return m_dData;
    }
private:
    int m_nData;
    double m_dData;
};
void main()
{
    Cls myCls;
    std::cout << "Data: " << myCls.GetData() << std::endl;
    std::cout << "Double: " << myCls.GetDouble() << std::endl;
}
以上程式碼用MSVC 2005測試,輸出的值為:
Data: -858993460
Double: -9.25596e+061
所以Google C++ Style Guide規定,當你的class中有定義data member而且沒有其它的ctor時,你必須自己定義一個default ctor,並且在這個default ctor中給予你的data member初值。例外是如果你的class繼承自現有的class而且沒有再加入新的data members,那你就不需要自己定義一個default ctor。
用到default ctor的場合如下:
1. Cls myCls;
2. Cls myArray[10];
3. Cls* pMyArray = new Cls[10];
4. std::vector<Cls> vec(10);
值得一提的是,若你class中的data member是其它的class type(比方說是std::string)的話,在你的class建構時會去呼叫該data member的ctor。
class CStudent
{
public:
    std::string GetName() const
    {
        return m_strName;
    }
private:
    std::string m_strName;
};
void main()
{
    CStudent myStudent;
    std::cout << "Name: " << myStudent.GetName() << std::endl;
}
以上程式在呼叫CStudent::GetName()時,會得到空字串;因為在建構CStudent myStudent時會呼叫std::string m_strName的ctor,而在std::string的ctor中會初始化為空字串。

coherence 發表在 痞客邦 留言(0) 人氣()

原文;
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables
規定程式中的non-local static object只能為POD,因為它們的ctor以及dtor的順序在C++中沒有被規範,這會造成難以解決的Bug;non-local static object為global或namespace scope的變數以及class中的static member data。
在同一個translation unit之中,global variables被初始化的順序即為它們被定義的順序。
class CFoo
{
public:
    CFoo()
    {
        std::cout << "CFoo ctor" << std::endl;
    }
};
class CBar
{
public:
    CBar()
    {
        std::cout << "CBar ctor" << std::endl;
    }
};
CFoo g_foo;
CBar g_bar;
void main()
{
    std::cout << "Main" << std::endl;
}
在上面的sample code之中,我們可以保證g_foo一定會在g_bar之前被初始化。所以上面sample code輸出的順序必為:
CFoo ctor
CBar ctor
Main
但是C++的spec卻沒有規範不同的translation unit之間,global variables的初始化順序。比方說,在下方的sample code之中,我們將無法確定g_foo和g_bar哪一個會先被初始化,使用不同編譯環境可能會產生不同的結果:
========== MyHeader.h ==========
class CFoo
{
public:
    CFoo()
    {
        std::cout << "CFoo ctor" << std::endl;
    }
};
class CBar
{
public:
    CBar()
    {
        std::cout << "CBar ctor" << std::endl;
    }
};
========== AAA.cpp ==========
#include "MyHeader.h"
CFoo g_foo;
========== BBB.cpp ==========
#include "MyHeader.h"
CBar g_bar;
如果CBar的的初始化需要依賴g_foo的話,將會產生難以發現的bug:
class CBar
{
public:
    CBar()
    {
        std::cout << "CBar ctor" << std::endl;
        m_nNumber = g_foo.GetData();
    }
private:
    int m_nNumber;
};
因為我們無法確定處在不同translation unit的g_bar與g_foo哪一個會先被初始化。所以Google C++ Style Guide規定global variable只能為Plain Old Data (POD)。解決這個問題的方法有很多,但最好的辦法還是直接禁止non-POD的global variable。
Google C++ Style Guide也進一步禁止由global function的return value來初始化static POD,因為global function有可能會依賴某些global variables。
C++ spec指出dtor呼叫的順序為ctor呼叫順序的相反,因為non-local static objects的ctor呼叫的順序是未知的,所以它們的dtor呼叫的順序也是未知的。在某個non-local static object被銷毀的時候,很有可能其它的non-local static objects正在使用它(可能在其它的thread),因而造成bug。
如果真的要使用class type的global variable,Google C++ Style Guide建議,可以將之宣告為指標(不能為smart pointer),並且在main()或pthread_once()裡面為該指標作初始化,用以避免初始化順序不確定的問題。
關於這個問題,文獻上還有其它的解決方法。

coherence 發表在 痞客邦 留言(0) 人氣()

原文:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Structs_vs._Classes
有關struct和class之間的觀念,成大SCREAM Lab的這篇文章寫的很好:
http://screamlab-ncku-2008.blogspot.tw/2009/10/c-struct-class-keywords.html

coherence 發表在 痞客邦 留言(0) 人氣()

原文:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Nonmember,_Static_Member,_and_Global_Functions
在軟體開發的過程中,有些時候有必要定義一個不和任何class instance有關聯的非class member function。此時我們應盡量少用global function,如果真的非要使用不可,應該將之放在namespace裡面,或是使用class的static member function作為替代方案。
因為使用completely global function(指未放在namespace裡的global function)會汙染全域的命名空間(global namespace)。比方說你自定義了一個global function名為sort(),而你#include進來的3rd party library中也定義了另一個sort(),此時就會造成命名碰撞的問題。

coherence 發表在 痞客邦 留言(0) 人氣()

原文:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
寫程式時很多時候都在追求所謂的code reuse,code的reusability越高代表程式中的duplicate code越少,而duplicate code常是bug的根源之一。回顧語言的發展,像是繼承(inheritance)、多型(polymorphism)、模板(template)...等language features的產生,design pattern、STL的使用,都提高了code的reusability。
傾向撰寫短小的函式,也是提高code reusability的方法之一。Google C++ Style Guide建議當一個函式超過40行(也有其他文獻建議是75行),你可以考慮在不影響程式結構的情況下拆解該函數,使之成為若干個小函數。當然40這個數字並不是個硬性規定,只是個參考值。

coherence 發表在 痞客邦 留言(0) 人氣()

1 2
Blog Stats
⚠️

成人內容提醒

本部落格內容僅限年滿十八歲者瀏覽。
若您未滿十八歲,請立即離開。

已滿十八歲者,亦請勿將內容提供給未成年人士。