C++的对象和类

一、问题引入

区分面向过程编程和面向对象编程的最大的特性就是 ,类是一种将抽象转换为用户定义类型的C++工具,它将数据表示和操纵数据的方法组合成一个整洁的包。

那么如何声明类、定义类、调用类?

C++ Primer Plus:中文版 (第六版) 的股票类举例说明。

二、解决过程

2-1 类抽象

股票类的抽象化

  • 获得股票

  • 增持股票

  • 卖出股票

  • 更新股票价格

  • 显示所持股票的信息

股票的数据类型抽象化

  • 发行股票公司名称

  • 所持股票的数量

  • 股票的单价

  • 股票总值

2-2 类的代码实现

1️⃣ stock.h

#ifndef __STOCK_H__
#define __STOCK_H__

#include <string>

// 类的声明
class Stock {
public:
    Stock(); // default constructor
    Stock(const std::string & co, long n = 0, double pr = 0.0); // constructor prototype with some default arguments
    ~Stock(); // noisy destructor

    void get_stock(const std::string & co, long n, double pr);  // 获得股票
    void add_stock(long num, double price);                     // 增持股票
    void sell_stock(long num, double price);                    // 卖出股票
    void update_price(double price);                            // 更新股票价格
    void show();                                                // 显示所持股票的信息

private:
    std::string company; // 发行股票公司名称
    long shares;         // 所持股票的数量
    double share_val;    // 股票的单价
    double total_val;    // 股票总值
    void set_total() {total_val = shares * share_val;};
};

#endif

2️⃣ stock.cpp

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

// default constructor
Stock::Stock()
{

}

// class destructor
Stock::~Stock() // verbose class destructor
{

}
// 构造函数的参数表示的不是类成员,而是赋给类成员的值。因此,参数名不能与类成员相同,否则出现同名混乱
Stock::Stock(const std::string & co, long n, double pr) 
{
    company = co;
    if(n < 0)
    {
        std::cerr << "Number of shares can't be negative; "
                  << company << " shares set to 0.\n";
        shares = 0;
    }
    else
        shares = n;
    share_val = pr;
    set_total();
}

/* other methods */

void Stock::get_stock(const std::string & co, long n, double pr) 
{
    company = co;
    if(n < 0)
    {
        std::cout << "Number of shares can't be negative; "
                  << company << " shares set to 0.\n";
        shares = 0;
    }
    else
        shares = n;
    share_val = pr;
    set_total();
}

void Stock::add_stock(long num, double price) 
{
    if(num < 0)
    {
        std::cout << "Number of shares purchased can't be negative. "
                  << "Transaction is aborted.\n";
    }
    else
    {
        shares += num;
        share_val = price;
        set_total();
    }
}

void Stock::sell_stock(long num, double price) 
{
    using std::cout;
    if(num < 0)
    {
        cout << "Number of shares sold can't be negative. "
             << "Transaction is aborted.\n";
    }
    else if(num > shares)
    {
        cout << "You can't sell more than you have! "
             << "Transaction is aborted.\n";
    }
    else
    {
        shares -=num;
        share_val = price;
        set_total();
    }
}

void Stock::update_price(double price) 
{
    share_val = price;
    set_total();
}

void Stock::show() 
{
    using std::cout;
    using std::endl;
    using std::ios_base;
    // set format to #.###
    ios_base::fmtflags orig = cout.setf(ios_base::fixed, ios_base::floatfield);
    std::streamsize prec = cout.precision(3);

    cout << "Stock Information:" << endl;
    cout << "Company company: " << company << endl;
    cout << "Number of Stocks: " << shares << endl;
    cout << "Price per Stock: $" << share_val<< endl;

    // set format to #.##
    cout.precision(2);
    cout << "Total Value: $" << total_val<< endl;

    // restore original format
    cout.setf(orig, ios_base::floatfield);
    cout.precision(prec);
}

3️⃣ stock_call.cpp

#include <iostream>
#include "..\inc\stock.h"

int main(void)
{
    Stock fluffy_the_cat("NanoSmart", 0, 0.0);
    fluffy_the_cat.get_stock("NanoSmart", 20, 12.50);
    fluffy_the_cat.show();
    std::cout << '\n';

    fluffy_the_cat.add_stock(15, 18.125);
    fluffy_the_cat.show();
    std::cout << '\n';

    fluffy_the_cat.sell_stock(400, 20);
    fluffy_the_cat.show();
    std::cout << '\n';

    fluffy_the_cat.add_stock(300000, 40.125);
    fluffy_the_cat.show();
    std::cout << '\n';

    fluffy_the_cat.sell_stock(300000, 0.125);
    fluffy_the_cat.show();

    return 0;
}

运行结果

C++的对象和类

2-3 同类的的比较

若用户希望根据类的某一个值进行比较,返回值较大的类,该如何实现。

在类的公共接口新增方法即可,此处以股票类举例:

stock.h

// 类的声明
class Stock {
public:
    // 此处省略重复信息
    const Stock & top_val(const Stock & s) const;               // 比较两只股票总值,得到总值较大的一只 

private:
    // 此处省略重复信息
};

stock.cpp

// 此处省略重复信息

 const Stock & Stock::top_val(const Stock & s) const
 {
    if (s.total_val > total_val)
        return s;
    else
        return *this;    
 }

main()

#include <iostream>
#include "..\inc\stock.h"

int main(void)
{
    Stock google, intel;
    google.get_stock("google", 100, 120);
    google.show();
    std::cout << '\n';

    intel.get_stock("intel", 100, 150);
    intel.show();
    std::cout << '\n';
    
    Stock top = google.top_val(intel);
    top.show();
    std::cout << '\n';

    return 0;
}

C++的对象和类

三、反思总结

一般来说,类规范由两部分组成。

  • 类声明:以数据成员的方式描述数据部分,以成员函数(即方法)的方式描述公有接口

  • 类方法定义:描述如何实现类成员函数

关于函数:const Stock & top_val(const Stock & s) const; 的理解

第一个 const :由于该函数返回了两个const 对象之一的引用,因此返回类型也应为const应用

第二个 const :该函数不会修改被显示地访问的对象(即 s)

第三个 const :该函数不会修改被隐式地访问的对象

this 指针指向用来调用成员函数的对象(this 被作为隐藏参数传递给方法)

四、参考引用

C++ Primer Plus:中文版 (第六版)

原文链接:https://www.cnblogs.com/caojun97/p/17305203.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++的对象和类 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • 【Visual Leak Detector】配置项 ReportTo

    说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍 VLD 配置文件中配置项 ReportTo 的使用方法。同系列文章目录可见 《内存泄漏检测工具》目录 目录 说明 1. 配置文件使用说明 2. 设置报告输出的位置 2.1 测试代码 2.2 ReportTo = debugger 时的输出 2.3 ReportTo = file 时的输出…

    C++ 2023年4月18日
    00
  • 08、【算例】openfoam溃坝

    7.1 溃坝 官网目录:$FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak 7.1.1 介绍 本案例使用interFoam两相算法,基于流体体积分数(VOF)法,每个网格中的相体积分数(alpha)通过求解一个组分运输方程确定。物理属性基于这个相分数通过加权平均计算。 7.1.2 网格生成 blockM…

    C++ 2023年4月18日
    00
  • luogu_P1040 [NOIP2003 提高组] 加分二叉树

    P1040 [NOIP2003 提高组] 加分二叉树 – 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意:给你一颗中序遍历为1到n的二叉树,和每个节点的val。树的值=左子树的值×右子树的值+根的val,空树值为1,求整个树最大值和这个值树的前序遍历。 题解:区间dp。dp[l][r]表示最大值,root[l][r]表示最大值的根,枚举区…

    C++ 2023年4月27日
    00
  • 【Visual Leak Detector】配置项 ForceIncludeModules

    说明 使用 VLD 内存泄漏检测工具辅助开发时整理的学习笔记。本篇介绍 VLD 配置文件中配置项 ForceIncludeModules 的使用方法。 同系列文章目录可见 《内存泄漏检测工具》目录 目录 说明 1. 配置文件使用说明 2. 设置需要检测的第三方模块 2.1 测试代码 2.2 ForceIncludeModules 为空时的输出 2.3 For…

    C++ 2023年4月18日
    00
  • Linux网络编程:socket实现client/server通信

    一、问题引入 阅读UNIX网络编程 卷1:套接字联网API 第3版的前4个章节,觉得有必要对书籍上的源码案例进行复现,并推敲TCP的C/S通信过程。 二、解决过程 2-1 server #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #in…

    C 2023年5月11日
    00
  • 最少步数

    在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就想试一试,在一个(100*100)的围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一…

    C++ 2023年4月25日
    00
  • C++动态分配(new)二维数组的若干方法

    写在前面 之前刷动态规划的题目,多需要用到二维数组(也许后面再优化成一维)。如果每次都按照给定数的范围直接声明为全局二维数组变量,又总觉得的不够优雅。查阅了一些网上的资料后,总结了一些使用方法,就写下这篇博文用以记录。 方法1——动态分配(new)一维数组,再强制类型转换为二维(个人使用,推荐指数:⭐⭐⭐⭐) 直接看例子 /** 假设需要根据两个string…

    C++ 2023年4月17日
    00
  • Qt源码阅读(四) 事件循环

    事件系统 文章为本人理解,如有理解不到位之处,烦请各位指正。 @ 目录 事件系统 什么是事件循环? 事件是如何产生的? sendEvent postEvent 事件是如何处理的? 事件循环是怎么遍历的? 事件过滤器 event 夹带私货时间 Qt的事件循环,应该是所有Qter都避不开的一个点,所以,这篇博客,咱们来了解源码中一些关于Qt中事件循环的部分。先抛…

    C++ 2023年4月18日
    00
合作推广
合作推广
分享本页
返回顶部