首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C++ 公有繼承導致成員變數變成隨機值:構造函數未正確鏈接基類

     編輯:程式設計疑難解答

錯誤現象

基類 `C` 有帶參構造函數 `C(float r, float h)` 初始化 `Radius`、`high`。派生類 `Round`、`Cylinder`、`Cone` 繼承 `C` 但未定義自己的構造函數調用基類構造函數。`main()` 中直接 `Round r; r.supArea();` 導致基類成員未初始化,讀取到隨機堆疊值。

根本原因

  • C++ 規則:派生類構造函數必須在初始化列表中顯式調用基類構造函數,否則嘗試調用基類預設構造函數。
  • 基類 `C` 未提供預設構造函數(僅有帶參構造),編譯器報錯或產生未初始化成員。
  • 原代碼中 `main()` 甚至建立了無用的 `C q(1,2);`,但派生類物件 `r`、`c1`、`c2` 從未傳遞參數給基類。

修正代碼:派生類添加構造函數鏈接基類

#include <iostream>
#include <cmath>
using namespace std;

const float Pi = 3.1415f;

class C {
public:
    C(float r, float h) : Radius(r), high(h) {}
protected:
    float Radius;
    float high;
};

class Round : public C {
public:
    Round(float r, float h) : C(r, h) {}  // 關鍵:調用基類構造
    void supArea();
    void volume();
};

void Round::supArea() {
    float s = 4 * Pi * pow(Radius, 2);
    cout << "\n球的表面積為:" << s << endl;
}
void Round::volume() {
    float v = 4 * Pi * pow(Radius, 3) / 3;
    cout << "\n球的體積為:" << v << endl;
}

class Cylinder : public C {
public:
    Cylinder(float r, float h) : C(r, h) {}
    void supArea();
    void volume();
};
void Cylinder::supArea() {
    float s = 2 * Pi * pow(Radius, 2) + high * 2 * Pi * Radius;
    cout << "\n圓柱的表面積為:" << s << endl;
}
void Cylinder::volume() {
    float v = Pi * pow(Radius, 2) * high;
    cout << "\n圓柱的體積為:" << v << endl;
}

class Cone : public C {
public:
    Cone(float r, float h) : C(r, h) {}
    void supArea();
    void volume();
};
void Cone::supArea() {
    float s = Pi * pow(Radius, 2) + Pi * Radius * high;
    cout << "\n圓錐的表面積為:" << s << endl;
}
void Cone::volume() {
    float v = 1.0f / 3 * Pi * pow(Radius, 2) * sqrt(pow(high, 2) - pow(Radius, 2));
    cout << "\n圓錐的體積為:" << v << endl;
}

int main() {
    Round r(1, 2);
    r.supArea(); r.volume();

    Cylinder c1(1, 2);
    c1.supArea(); c1.volume();

    Cone c2(1, 2);
    c2.supArea(); c2.volume();
    return 0;
}

關鍵修正點

錯誤修正
派生類無構造函數添加 `Round(float r, float h) : C(r, h) {}` 等
`main()` 中 `Round r;` 無參數改為 `Round r(1, 2);` 傳遞半徑、高度
`Cone::volume()` 整數除法 `1/3` 為 0改為 `1.0f/3` 強制浮點除法
`pow(Radius, 2)` 重複計算可優化為 `Radius*Radius`,非必須

最佳實務建議

  1. 基類若有帶參構造,**必須**在派生類構造函數初始化列表中顯式調用。
  2. 2. 基類建議提供 `protected` 預設構造函數(若語義允許),或 `= delete` 禁止預設構造,強制派生類傳參。 3. 成員變數命名避免與基類同名(或用 `m_` 前綴),減少遮蔽混淆。 4. 虛擬解構函數:基類應宣告 `virtual ~C() = default;`,確保多態刪除正確。 5. 使用 `override`、`final` 關鍵字(C++11)增強編譯期檢查。

總結

「公有繼承後成員變隨機值」經典癥結在於派生類未正確鏈接基類構造函數。牢記「派生類構造 = 基類構造 + 自身初始化」,在初始化列表中傳遞參數,即可確保繼承體系中所有成員正確初始化。

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