楼主: a大卫盗金
77 0

[教育经济学基本知识] C++ Prime Plus 学习笔记026 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2018-4-20
最后登录
2018-4-20

楼主
a大卫盗金 发表于 昨天 21:17 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

书籍:C++ Primer Plus (第六版)(中文版)
开发工具:Dev-C++ 5.11
计算机配置:Intel Xeon CPU E5-2603 v3 @ 1.60GHz
系统信息:Windows 10 专业版,64位操作系统,基于x64的处理器

第11章 类的应用

11.4 运算符重载:成员函数与非成员函数的选择

在C++中,运算符重载可以通过类的成员函数或全局的非成员函数实现。选择哪种方式取决于具体需求。通常情况下,若运算符需要修改对象状态或自然地作用于左侧操作数,则定义为成员函数更合适;而当涉及类型转换、对称性操作(如两个操作数都可能被隐式转换),或需访问私有成员但不改变对象时,使用友元函数更为合理。

11.5 深入探讨运算符重载:构建矢量类

本节通过一个完整的vector类示例,展示如何合理设计并重载多个运算符,以支持直观的数学操作。该类支持直角坐标系(RECT)和极坐标系(POL)两种表示模式,并可在两者之间自动转换。

头文件定义:vector.h

#ifndef VECTOR_H_
#define VECTOR_H_
#include <iostream>

namespace VECTOR
{
    class vector
    {
    public:
        enum Mode { RECT, POL };
    
    private:
        double x;
        double y;
        double mag;
        double ang;
        Mode mode;
        
        void set_mag();
        void set_ang();
        void set_x();
        void set_y();
    
    public:
        vector();
        vector(double n1, double n2, Mode form = RECT);
        void reset(double n1, double n2, Mode form = RECT);
        ~vector();
        
        double xval() const { return x; }
        double yval() const { return y; }
        double magval() const { return mag; }
        double angval() const { return ang; }
        
        void polar_mode();
        void rect_mode();
        
        vector operator+(const vector & b) const;
        vector operator-(const vector & b) const;
        vector operator-() const;
        vector operator*(double n) const;
        
        friend vector operator*(double n, const vector & a);
        friend std::ostream & operator<<(std::ostream & os, const vector & v);
    };
}
#endif
[此处为图片1]

实现文件:vector.cpp

#include <cmath>
#include "vector.h"

using std::sqrt;
using std::sin;
using std::cos;
using std::atan;
using std::atan2;
using std::cout;

namespace VECTOR
{
    const double Rad_to_deg = 45.0 / atan(1.0);

    void vector::set_mag()
    {
        mag = sqrt(x * x + y * y);
    }

    void vector::set_ang()
    {
        if (x == 0.0 && y == 0.0)
            ang = 0.0;
        else
            ang = atan2(y, x);
    }

    void vector::set_x()
    {
        x = mag * cos(ang);
    }

    void vector::set_y()
    {
        y = mag * sin(ang);
    }

    vector::vector()
    {
        x = y = mag = ang = 0.0;
        mode = RECT;
    }

    vector::vector(double n1, double n2, Mode form)
    {
        mode = form;
        if (form == RECT)
        {
            x = n1;
            y = n2;
            set_mag();
            set_ang();
        }
        else if (form == POL)
        {
            mag = n1;
            ang = n2 / Rad_to_deg;
            set_x();
            set_y();
        }
        else
        {
            cout << "Incorrect 3rd argument to vector() --";
            cout << "vector set to 0\n";
            x = y = mag = ang = 0.0;
            mode = RECT;
        }
    }

    void vector::reset(double n1, double n2, Mode form)
    {
        mode = form;
        if (form == RECT)
        {
            x = n1;
            y = n2;
            set_mag();
            set_ang();
        }
        else if (form == POL)
        {
            mag = n1;
            ang = n2 / Rad_to_deg;
            set_x();
            set_y();
        }
        else
        {
            cout << "Incorrect 3rd argument to vector() --";
            cout << "vector set to 0\n";
            x = y = mag = ang = 0.0;
            mode = RECT;
        }
    }

    vector::~vector()
    {
    }

    void vector::polar_mode()
    {
        mode = POL;
    }

    void vector::rect_mode()
    {
        mode = RECT;
    }

    vector vector::operator+(const vector & b) const
    {
        return vector(x + b.x, y + b.y);
    }

    vector vector::operator-(const vector & b) const
    {
        return vector(x - b.x, y - b.y);
    }

    vector vector::operator-() const
    {
        return vector(-x, -y);
    }

    vector vector::operator*(double n) const
    {
        return vector(n * x, n * y);
    }

    vector operator*(double n, const vector & a)
    {
        return a * n;
    }

    std::ostream & operator<<(std::ostream & os, const vector & v)
    {
        if (v.mode == vector::RECT)
            os << " (x,y) = (" << v.x << ", " << v.y << ")";
        else if (v.mode == vector::POL)
        {
            os << " (m,a) = (" << v.mag << ", "
                << v.ang * Rad_to_deg << ")";
        }
        else
            os << "vector object mode is invalid";
        return os;
    }
}
[此处为图片2]
vector::vector() 
{
    x = y = mag = ang = 0.0;
    mode = RECT;
}

vector::~vector()
{
}

void vector::polar_mode()
{
    mode = POL;
}

void vector::rect_mode()
{
    mode = RECT;
}

vector vector::operator+(const vector & b) const
{
    return vector(x + b.x, y + b.y);
}

vector vector::operator-(const vector & b) const
{
    return vector(x - b.x, y - b.y);
}

vector vector::operator*(double n) const
{
    return vector(n * x, n * y);
}

vector operator*(double n, const vector & a)
{
    return a * n;
}

std::ostream & operator<<(std::ostream & os, const vector & v)
{
    if (v.mode == vector::RECT)
    {
        os << "(x,y) = (" << v.x << ", " << v.y << ")";
    }
    else if (v.mode == vector::POL)
    {
        os << "(m,a) = (" << v.mag << ", " << v.ang * Rad_to_deg << ")";
    }
    else
    {
        os << "vector object mode is invalid.";
    }
    return os;
}
[此处为图片1]
randwalk.cpp  
#include <iostream>  
#include <cstdlib>  
#include <ctime>  
#include "vector.h"  

int main()  
{  
    using namespace std;  
    using VECTOR::vector;  

    srand(time(0));  
    double direction;  
    vector step;  
    vector result(0.0, 0.0);  
    unsigned long steps = 0;  
    double target;  
    double dstep;  

    cout << "Enter target distance (q to quit): ";  

    while (cin >> target)  
    {  
        cout << "Enter step length: ";  
        if (!(cin >> dstep))  
            break;  

        while (result.magval() < target)  
        {  
            direction = rand() % 360;  
            step.reset(dstep, direction, vector::POL);  
            result = result + step;  
            steps++;  
        }  

        cout << "After " << steps << " steps, the subject "  
                  "has the following location:\n";  
        cout << result << endl;  

        result.polar_mode();  
        cout << " or\n" << result << endl;  

        cout << "Average outward distance per step = "  
                  << result.magval() / steps << endl;  

        steps = 0;  
        result.reset(0.0, 0.0);  
        cout << "Enter target distance (q to quit): ";  
    }  

    cout << "Bye!\n";  
    cin.clear();  
    while (cin.get() != '\n')  
        continue;  

    return 0;  
}
[此处为图片2]
运行结果示例:  
Enter target distance (q to quit): 50  
Enter step length: 2  
After 256 steps, the subject has the following location:  
(x,y) = (49.2231, -11.0343)  
or  
(m,a) = (50.4447, -12.635)  
Average outward distance per step = 0.19705  
Enter target distance (q to quit): 50
Enter step length: 2
After 634 steps, the subject has the following location:
(x,y) = (-43.8145, -25.971)
or
(m,a) = (50.9333, -149.343)
Average outward distance per step = 0.0803365
Enter target distance (q to quit): 50
Enter step length: 1
After 399 steps, the subject has the following location:
(x,y) = (-50.3994, -1.21405)
or
(m,a) = (50.4141, -178.62)
Average outward distance per step = 0.126351
Enter target distance (q to quit): q
Bye!
--------------------------------
Process exited after 56.52 seconds with return value 0
请按任意键继续. . .

11.6 类型的自动转换与显式类型转换

在C++中,类可以支持从基本数据类型到类类型的自动转换,也可以通过构造函数实现隐式类型转换。此外,还可以定义强制类型转换操作来控制对象如何被转换为其他类型。

示例:11.6

文件:stonewt.h
#ifndef STONEWT_H_
#define STONEWT_H_

class Stonewt
{
private:
    enum { Lbs_per_stn = 14 }; // 每英石包含的磅数
    int stone;                 // 英石部分
    double pds_left;            // 剩余的磅数
    double pounds;              // 总重量(以磅为单位)

public:
    Stonewt(double lbs);        // 从磅构造
    Stonewt(int stn, double lbs); // 从英石和磅构造
    Stonewt();                  // 默认构造函数
    ~Stonewt();                 // 析构函数

    void show_lbs() const;      // 显示总磅数
    void show_stn() const;      // 显示英石和剩余磅数
};

#endif
文件:stonewt.cpp
#include <iostream>
#include "stonewt.h"
using std::cout;

Stonewt::Stonewt(double lbs)
{
    stone = static_cast<int>(lbs) / Lbs_per_stn;
    pds_left = static_cast<int>(lbs) % Lbs_per_stn + lbs - static_cast<int>(lbs);
    pounds = lbs;
}

Stonewt::Stonewt(int stn, double lbs)
{
    stone = stn;
    pds_left = lbs;
    pounds = stn * Lbs_per_stn + lbs;
}

Stonewt::Stonewt()
{
    stone = 0;
    pounds = 0;
    pds_left = 0;
}

Stonewt::~Stonewt()
{
    // 析构函数为空
}

void Stonewt::show_stn() const
{
    cout << stone << " stone, " << pds_left << " pounds.\n";
}

void Stonewt::show_lbs() const
{
    cout << pounds << " pounds.\n";
}
文件:stone.cpp
#include <iostream>
#include "stonewt.h"
using std::cout;

void display(const Stonewt &st, int n);

int main()
{
    Stonewt incognito = 275;         // 隐式转换:double → Stonewt
    Stonewt wolfe(285.7);             // 显式构造
    Stonewt taft(21, 8);              // 使用两个参数构造

    cout << "The celebrity weighed ";
    incognito.show_stn();

    cout << "The detective weighed ";
    wolfe.show_stn();

    cout << "The President weighed ";
    taft.show_lbs();

    incognito = 276.8;                // 赋值触发隐式转换
    taft = 325;                       // 同样是隐式转换

    cout << "After dinner, the President weighed ";
    taft.show_lbs();

    display(taft, 2);                 // 传递对象
    cout << "The wrestler weighed even more.\n";
    display(422, 2);                  // 临时对象由整数隐式创建
    cout << "No stone left unearned\n";

    return 0;
}

void display(const Stonewt &st, int n)
{
    for (int i = 0; i < n; ++i)
    {
        cout << "Wow! ";
        st.show_stn();
    }
}

在程序运行后,得到了以下输出结果:

名人的体重为 19 英石 9 磅。

侦探的体重达到了 20 英石 5.7 磅。

总统先生的初始体重是 302 磅。

用餐之后,总统的体重上升至 325 磅。

令人惊讶的是,当前体重已达到 23 英石 3 磅。

再次确认:23 英石 3 磅。

[此处为图片1]

而那位摔跤手的体重更是惊人。

竟然高达 30 英石 2 磅!

重复验证:30 英石 2 磅!

所有数据均被完整记录,无一遗漏。


示例代码 11.7

头文件 stonewt1.h

#ifndef STONEWT1_H_
#define STONEWT1_H_

class Stonewt
{
private:
    enum { Lbs_per_stn = 14 };
    int stone;
    double pds_left;
    double pounds;

public:
    Stonewt(double lbs);
    Stonewt(int stn, double lbs);
    Stonewt();
    ~Stonewt();

    void show_lbs() const;
    void show_stn() const;

    operator int() const;
    operator double() const;
};

#endif

实现文件 stonewt1.cpp

#include <iostream>
#include "stonewt1.h"
using std::cout;

Stonewt::Stonewt(double lbs)
{
    stone = static_cast<int>(lbs) / Lbs_per_stn;
    pds_left = static_cast<int>(lbs) % Lbs_per_stn + lbs - static_cast<int>(lbs);
    pounds = lbs;
}

Stonewt::Stonewt(int stn, double lbs)
{
    stone = stn;
    pds_left = lbs;
    pounds = stn * Lbs_per_stn + lbs;
}

Stonewt::Stonewt()
{
    stone = pounds = pds_left = 0;
}

Stonewt::~Stonewt()
{
}

void Stonewt::show_stn() const
{
    cout << stone << " stone, " << pds_left << " pounds.\n";
}

void Stonewt::show_lbs() const
{
    cout << pounds << " pounds.\n";
}

Stonewt::operator int() const
{
    return static_cast<int>(pounds + 0.5);
}

Stonewt::operator double() const
{
    return pounds;
}

主程序文件 stone1.cpp

#include <iostream>
#include "stonewt1.h"

int main()
{
    using std::cout;
    Stonewt poppins(9, 2.8);
    double p_wt = poppins;

    cout << "Convert to double => ";
    cout << "poppins: " << p_wt << " pounds.\n";

    cout << "Convert to int => ";
    cout << "poppins: " << int(poppins) << " pounds.\n";

    return 0;
}

编译并执行后的结果显示如下:

转换为 double 类型 => poppins: 128.8 磅。

转换为 int 类型 => poppins: 129 磅。

[此处为图片2]

程序成功运行,耗时约 0.02376 秒,返回值为 0。

按任意键继续...

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:prime 学习笔记 PLUS Rim IME

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-5 18:33