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

C++ 拷貝建構子與 sqrt 參數型別錯誤修正:Line 類長度計算實戰除錯

     編輯:程式設計綜合問答

初學 C++ 時常遇到兩類經典錯誤:拷貝建構子參數未加 const 導致無法接受暫時物件,以及 數學函式參數型別不匹配。本文以一個 Point-Line 幾何類為例,逐步修正編譯錯誤與邏輯缺陷。

原始程式碼問題清單


class Point {
public:
    Point(int xx=0, int yy=0) : x(xx), y(yy) {}
    Point(Point &p); // ❌ 非 const 參考,無法綁定暫時物件
    // ...
};

class Line {
public:
    Line(Point &pp1, Point &pp2); // ❌ 同理
    Line(int x1, int y1, int x2, int y2) : p1(x1,y1), p2(x2,y2) {
        int x = static_cast(p1.GetX() - p2.GetX()); // ❌ static_cast 缺少目標型別
        int y = static_cast(p1.GetY() - p2.GetY());
        len = sqrt(x*x + y*y); // ❌ sqrt 需 double,傳入 int 可能精度損失/警告
    }
    Line(Line &l1); // ❌ 同理
    // ...
};

修正版完整程式碼


#include 
#include 
using namespace std;

class Point {
public:
    Point(int xx = 0, int yy = 0) : x(xx), y(yy) {}
    // ✅ 加上 const,可接受暫時物件與常數物件
    Point(const Point &p) : x(p.x), y(p.y) {
        cout << "Point 拷貝建構子" << endl;
    }
    int GetX() const { return x; } // ✅ 加 const
    int GetY() const { return y; }
private:
    int x, y;
};

class Line {
public:
    Line() : len(0) { cout << "Line 預設建構子" << endl; }
    // ✅ 參數加 const
    Line(const Point &pp1, const Point &pp2) : p1(pp1), p2(pp2) {
        calcLen();
    }
    Line(int x1, int y1, int x2, int y2) : p1(x1, y1), p2(x2, y2) {
        calcLen();
    }
    Line(const Line &l1) : p1(l1.p1), p2(l1.p2), len(l1.len) {
        cout << "Line 拷貝建構子" << endl;
    }
    double GetLen() const { return len; } // ✅ 回傳 double 更精確
    ~Line() {}
private:
    Point p1, p2;
    double len; // ✅ 用 double 存儲長度
    void calcLen() {
        double dx = static_cast(p1.GetX() - p2.GetX()); // ✅ 明確轉 double
        double dy = static_cast(p1.GetY() - p2.GetY());
        len = sqrt(dx * dx + dy * dy); // ✅ sqrt 接收 double
    }
};

int main() {
    Point p1(3, 7), p2(9, 4);
    Line line(p1, p2);       // 呼叫 Line(const Point&, const Point&)
    Line line2(line);        // 呼叫 Line(const Line&)
    cout << "The length of the line is: " << line.GetLen() << endl;
    cout << "The length of the line2 is: " << line2.GetLen() << endl;
    return 0;
}

關鍵修正點解析

錯誤類型原寫法修正原因
拷貝建構子參數Point(Point &p)Point(const Point &p)非 const 參考無法綁定右值(如 Point()、函式回傳值)
static_cast 語法static_cast(p1.GetX()-p2.GetX())static_cast(...)必須指定目標型別 <type>
sqrt 參數型別sqrt(x*x + y*y) (x,y 為 int)sqrt(double(dx*dx + dy*dy))sqrt 多載為 double/float/long double,整數會隱性轉換但可能精度損失/警告
長度儲存型別int lendouble len幾何長度通常非整數,int 會截斷
Getter 加 constint GetX()int GetX() const允許在 const 物件上呼叫,符合語意

編譯器警告等級建議

開啟 -Wall -Wextra -Wpedantic (GCC/Clang) 或 /W4 (MSVC),上述錯誤在編譯期即可被攔截:

  • binding reference of type 'Point&' to 'const Point' discards qualifiers
  • missing template arguments before '(' token (static_cast)
  • conversion from 'int' to 'double' may alter its value

總結

C++ 型別系統嚴格而強大:拷貝建構子必須取 const 參考、數學運算盡早轉 double、唯讀方法標記 const。養成這些習慣,可消除 80% 以上的初學者編譯/執行期錯誤,寫出型別安全、效能穩健的 C++ 程式碼。

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