首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++ 進階必知:繼承、虛函數、函數指針、動態數組與模板技巧

     編輯:關於C++

類對象內存佈局與繼承大小

理解繼承(含虛繼承)下對象大小是 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 為編譯期常量;動態雙維需用指針數組。

dynamic_cast 跨類轉換與指針偏移

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++」的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved