C++:不允許 在建構函式中呼叫另一個建構函式 (C++11 前)。
struct Point {
int X, Y;
Point(int x, int y);
Point(Point p) : Point(p.X, p.Y) { } // 編譯錯誤
};
C#:允許 使用 this(...) 語法委派。
struct Point {
public int X, Y;
public Point(int x, int y) { X = x; Y = y; }
public Point(Point p) : this(p.X, p.Y) { } // 合法
}
原因:C++ 建構/解構配對嚴格,委派會導致建構執行兩次、解構一次 → 資源管理破壞。C# 由 GC 管理記憶體,無此顧慮。
C++:建構期間虛擬呼叫**被編譯器解析為靜態呼叫** (呼叫基類版本)。
struct Base {
Base() { VirtualFunc(); } // 呼叫 Base::VirtualFunc
virtual void VirtualFunc() { cout << "Base"; }
};
struct Derived : Base {
Derived() { }
void VirtualFunc() override { cout << "Derived"; }
};
// new Derived() 輸出 "Base"
原因:C++ 物件佈局在基類建構時尚未完成,虛函式表仍指向基類版本。
C#:建構函式中**正常進行虛擬分派** (呼叫衍生類覆寫版本)。
class Base {
public Base() { VirtualMethod(); }
public virtual void VirtualMethod() => Console.WriteLine("Base");
}
class Derived : Base {
public Derived() { }
public override void VirtualMethod() => Console.WriteLine("Derived");
}
// new Derived() 輸出 "Derived"
原因:CLR 在物件配置時即建立完整型別資訊 (MethodTable),虛擬呼叫機制即刻生效。
| 場景 | C++ 建議 | C# 建議 |
|---|---|---|
| 共用初始化邏輯 | 私有 Init() 方法、或 C++11 委派建構 | 直接 this(...) 委派 |
| 建構中呼叫虛擬方法 | **嚴禁** (行為違反直覺) | **謹慎使用** (衍生類欄位可能未初始化) |
| 資源獲取即初始化 (RAII) | 核心慣用語 | 改用 using/IDisposable |
兩語言建構函式語義差異源於「記憶體管理模型」根本不同:C++ 手動 RAII、C# 自動 GC。跨語言開發時,**切勿將 C++ 直覺直接套用 C#**,反之亦然。