程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++的可移植性和跨平台開發[2]:語法

C++的可移植性和跨平台開發[2]:語法

編輯:關於C++

目前還有相當一部分開發人員在使用老式編譯器干活,這些老式編譯器可能對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/

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved