針對不完全支援 C++98 的舊編譯器 (如 VC6),透過避開新語法 保證移植性。現代編譯器可忽略此類限制。
for 迴圈變數作用域
// C++98: 變數僅在迴圈內
// VC6: 變數洩漏到外層作用域
for (int i=0; i
// 危險:跨檔全域物件相依
// 安全:函式內靜態區域變數 (C++11 執行緒安全)
T& getInstance() {
static T instance; // 首次呼叫初始化
return instance;
}
註:單例解決建構順序,但解構順序仍有風險。
inline 函數限制static 區域變數 (各編譯單元會有獨立副本)。...)。
void foo(int a, int b);
int n = 1;
foo(++n, ++n); // a,b 值不確定 (可能 2,3 或 3,2)
// 規避:分離副作用
int a = ++n;
int b = ++n;
foo(a, b);
舊編譯器可能不支援。避免複雜特化,改用標記類別/多載。
template class Base {
protected:
typedef std::vector Container;
Container data_;
};
template class Derived : public Base {
using Base::Container; // 必須引入
using Base::data_;
void func() {
Container c; // OK: 已引入
// Container c; // 錯誤: 未引入時依賴非標準查找
data_.clear(); // OK: 已引入
// this->data_.clear(); // 另一種寫法
}
};
typeid/type_info) 可移植性差type_info 規定極少,實作差異大 (如 name() 回傳字串格式)。operator==/operator!=。CRuntimeClass, wxWidgets)。
// 錯誤:內部類別非友元
class Outer {
int secret;
class Inner { void f(Outer* o) { cout << o->secret; } };
};
// 正確:前置宣告 + 友元宣告
class Outer {
int secret;
class Inner; friend class Inner;
class Inner { void f(Outer* o) { cout << o->secret; } };
};
void foo(short); void foo(long);
foo(0); // 0 是 int,轉 short 與 long 皆為標準轉換 → 多義性
// 規避:避免此類多載組合,或用強型別包裝
int、wchar_t、long 大小隨平台變化。int32_t 等定長型別。
class Foo {
static const int MIN = 0; // VC6 錯誤
enum { MAX = 64 }; // 通用
};