目前還有相當一部分開發人員在使用老式編譯器干活,這些老式編譯器可能對C++98支持 不夠。因此,當你的代碼移植到這些老式的編譯器上時,可能會碰到一些稀奇古怪的問題( 包括編譯出錯和運行時錯誤)。下面這些注意事項有助於你繞過這些問題。
強調一下 ,後面提到的好幾個條款都是通過回避C++的新語法來保證移植性。如果你用的是新式編譯器 ,那麼你可以不理會這些條款。
★小心for循環變量的作用域(不支持新標准)
在C++98標准中,for循環變量的作用域局限在循環體內。而某些老的編譯器(例如 Visual C++ 6)認為for循環變量的作用域在循環體外。所以如下的代碼可能導致移植問題。
{
for(int i=0; i<XX; i++)
{
// ...
}
for(int i=0; i<XXX; i++)
{
// ...
}
}
建議修改為不同的循環變量,如下所示:
{
for (int i=0; i<XX; i++)
{
// ...
}
for(int j=0; j<XXX; j++)
{
// ...
}
}
★不 要使用全局類對象,改用單鍵(標准未定義)
全局類對象的構造函數先於main()函數 執行,如果某個模塊中同時包含若干個全局類對象,則它們的構造函數的調用順序是不確定 的。而單鍵是在第一次調用時被初始化,能避免此問題。另外,單鍵雖然解決了構造問題, 但是析構依然有隱患。詳見“C++ 對象是怎麼死的?進程篇”。
★保持 inline函數盡量簡單
不要在inline函數內部使用局部靜態變量,不要在inline函數使 用可變參數。這些都有可能導致移植問題。
★不要依賴函數參數的求值順序(標准未 定義)
標准沒有明確規定函數參數的求值順序。因此,如下的代碼行為是不確定的。
void Foo(int a, int b);
int n = 1;
foo(++n, ++n);
★慎用模板特化(不支持新標准)
有些老式編譯器對偏特化或 全特化支持不夠。
★模板繼承中,引用基類成員要小心(不支持新標准)
看 如下例子:
template <typename T>
class TBase
{
protected:
typedef std::vector<T> Container;
Container m_container;
};
template <typename T>
class TDerived : public TBase<T>
{
typedef TBase<T> BaseClass;
public:
void Func()
{
typename BaseClass::Container foo; //可移植
Container foo; //不可移植
this- >m_container.clear(); //可移植
m_container.clear(); //不可移植
}
};
★慎用RTTI(不支持新標准、標准未定義)
先聲明一 下,我這裡說的RTTI主要是指typeid操作符和type_info類型。
首先,由於某些老式 編譯器可能不支持typeid操作符和type_info類型,會導致移植性的問題,這是慎用RTTI的一 個原因。(如果你用的是新式編譯器,不用考慮這個因素)
其次,由於標准對於 type_info類型的約束比較簡單。這導致了不同的編譯器對type_info的實現有較大差異。如 果你確實要使用type_info類型,建議僅僅使用它的operator==和operator!=這兩個成員函數 。
所以,如果你確實需要在運行時確定類型,又不想碰到上述問題,可以考慮在自己 的類體系中加入類型信息來實現。比如MFC和wxWidgets都是這麼干的。
★慎用嵌套類 (不支持新標准)
如果在內部類訪問外部類的非公有成員,要把內部類聲明為外部類 的friend。
如下代碼存在移植問題。
class COuter
{
private:
char* m_name;
public:
class CInner
{
void Print(COuter* outer)
{
cout << outer- >m_name;
}
};
};
應該改為如下代碼
class COuter
{
private:
char* m_name;
public:
class CInner; //前置聲明
friend class CInner;
class CInner
{
void Print(COuter* outer)
{
cout << outer->m_name;
}
};
};
★ 不要定義參數類型相近的函數(標准未定義)
void Foo(short n);
void Foo(long n);
Foo(0); //會導致二義性錯誤
★不要依賴標 准類型的字長(標准未定義)
某些標准類型(例如int、wchar_t)的字長會隨著具體 的平台而改變。
★用枚舉代替類的靜態成員常量(不支持新標准)
某些老式 的編譯器不支持類的靜態成員常量,可以用枚舉來代替。
class CFoo
{
static const int MIN = 0; //不可移植
enum { MAX = 64 }; //可移植
};
今天說了這麼一大堆,都比較瑣碎,估計會有遺漏 的。日後如果大伙兒發現有補充的,歡迎在本帖的評論中指教一二。由於篇幅有限,我把和 異常相關的內容留到下一個話題。
原始地址:http://program- think.blogspot.com/