理解繼承(含虛繼承)下對象大小是 C++ 面試與底層調試的核心考點。
class A { char a[100]; }; // sizeof(A) = 100
class B : public A { char b[100]; };// sizeof(B) = 200 (A + B)
class C : public A { char c[100]; };// sizeof(C) = 200
class D : public B, public C { // 多重繼承,含兩個 A 子對象
char d[100];
};// sizeof(D) = 100(A) + 100(B) + 100(C) + 100(D) = 400
class E : public virtual A { char e[100]; };// sizeof(E) = 100(A) + 100(E) + 指針/vptr ≈ 208
class F : public virtual B { char f[100]; };// B 虛繼承 A,F 共享同一 A 子對象
虛繼承引入 虛基類指針(或 vbptr),使派生類對象中只保留一份虛基類實例,解決「菱形繼承」數據冗余問題。
CDiamondClass1 構造 CBaseClass1)。利用引用保持數組類型,推導長度:
template <typename T, size_t N>
void printArrLength(T (&arr)[N]) {
cout << "大小: " << sizeof(arr) << ", 長度: " << N
<< ", 元素大小: " << sizeof(arr)/N << endl;
}
int a[] = {1,2,3,4,5};
printArrLength(a); // 輸出 長度: 5
struct CBaseClass1 {
CBaseClass1(size_t n): m_val(n) {}
size_t m_val;
};
struct CSubClassV1 : public virtual CBaseClass1 {
CSubClassV1(size_t n): CBaseClass1(n) {}
};
struct CSubClassV2 : public virtual CBaseClass1 {
CSubClassV2(size_t n): CBaseClass1(n) {}
};
struct CDiamondClass1 : public CSubClassV1, public CSubClassV2 {
CDiamondClass1(size_t n): CBaseClass1(n), CSubClassV1(n), CSubClassV2(n) {}
};
此處 CDiamondClass1 必須顯式調用虛基類構造函數,否則編譯錯誤。
void fa() { cout << "hello fa\n"; }
void fb() { cout << "hello fb\n"; }
void fc() { cout << "hello fc\n"; }
typedef void (*FuncPtr)(); // 返回 void、無參的函數指針類型
int main() {
FuncPtr fp;
char c; cin >> c;
switch(c) {
case 'a': fp = &fa; break;
case 'b': fp = &fb; break;
case 'c': fp = fc; break; // 函數名隱式轉換為指針
}
if (fp) fp(); // 調用
}
void new2DArray(int rows, int cols) {
int** p = new int*[rows];
for (int i = 0; i < rows; ++i)
p[i] = new int[cols];
// 使用 p[i][j]
for (int i = 0; i < rows; ++i) delete[] p[i];
delete[] p;
}
注意:new int[rows][cols] 要求 cols 為編譯期常量;動態雙維需用指針數組。
class A {}; class B {}; class C : public A, public B {};
C* pc = new C();
B* pb = dynamic_cast(pc);
cout << (void*)pc - (void*)pb; // 輸出偏移量(如 200),驗證多重繼承內存佈局
operator<< 的友元聲明技巧關鍵:在類模板內聲明友元時,需指明函數模板實例化:
template <class V, class A>
class MGraph {
friend ostream& operator<< <>(ostream&, const MGraph<V,A>&); // <> 表示函數模板
};
定義時:
template <class V, class A>
ostream& operator<<(ostream& os, const MGraph<V,A>& G) { ... }
掌握對象模型、虛繼承、模板元編程、函數指針、動態內存管理等核心機制,是從「會用 C++」進階為「精通 C++」的關鍵。