C++类的实例:Stock(股票)类。

简介: C++类的实例:Stock(股票)类。

从C过渡到C++,类是一个新的概念。

类是由数据表示和操纵数据的方法组合成的一个包。

本文使用一个例子(Stock)来加深对类的理解。

 

使用C++类来表示一个物体,首先要考虑类需要包含的内容。

对于股票来说,需要包含的内容很多。

先考虑可以对股票进行的操作:获得股票;买入;卖出;更新股票价格;显示股票信息。

然后考虑股票需要存储的信息:公司名称;股票数量;每股价格;股票总值。

接下来定义类,

类有两部分,类声明(声明数据成员和成员函数)和类定义(实现成员函数)。

​//stock.h
class Stock   //类声明 class
{
private:  //私有成员 private
  std::string company; //公司名称,所持股票数量,每股价值,股票总值。
  long shares;
  double share_val;
  double total_val;
  void set_tot() { total_val = shares * share_val; }
public:   //公有成员,外部接口 public
    void acquire(const std::string & co ,long n ,double pr);
  void buy(long num, double price); //功能函数
  void sell(long num, double price);
  void update(double price);
  void show()const;
};
 
//stock.cpp stock类的具体实现
 
#include<iostream>
#include"stock.h"
 
 
void Stock::buy(long num, double price)
{
  if (num < 0)
  {
    std::cout << "shares 买入不能为负。"
      << "放弃操作。\n";
  }
  else
  {
    shares += num;
    share_val = price;
    set_tot();
  }
}
void Stock::sell(long num, double price)
{
  using std::cout;
  if (num < 0)
  {
    cout << "售出shares不能为负。"
      << "放弃售出操作。\n";
  }
  else if (num > shares)
  {
    cout << "售出不能大于所有。"
      << "放弃售出操作。\n";
  }
  else
  {
    shares -= num;
    share_val = price;
    set_tot();
  }
}
void Stock::update(double price)
{
  share_val = price;
  set_tot();
}
void Stock::show() const
{
  using std::cout;
  using std::ios_base;
  //此处为输出格式的设置,略看
  ios_base::fmtflags orig =
    cout.setf(ios_base::fixed, ios_base::floatfield);
  std::streamsize prec = cout.precision(3);
 
  cout << "公司:" << company
    << " 股份:" << shares << '\n'
    << "每股价格: $" << share_val;
  cout.precision(2);
  cout << " 总值: $" << total_val << '\n';
 
  //恢复原来的设置,避免影响其他输出。
  cout.setf(orig, ios_base::floatfield);
  cout.precision(prec);
}
 
 

以上完成了对Stock类的初步定义。

接下来可以使用Stock类(使用多文件程序方法,将stock.cpp和stock.h放在主函数的同一工程内)

#include<iostream>
#include"stock.h"
int main()
{
  Stock fluffy_the_cat;
  fluffy_the_cat.acquire("NanoSmart", 20, 12.50);
  fluffy_the_cat.show();
  fluffy_the_cat.buy(15, 18.125);
  fluffy_the_cat.show();
  fluffy_the_cat.sell(400, 20.00);
  fluffy_the_cat.show();
  fluffy_the_cat.buy(300000, 40.25);
  fluffy_the_cat.show();
  fluffy_the_cat.sell(300000, 0.125);
  fluffy_the_cat.show();
  system("pause");
  return 0;
}

至此,完成了Stock类的创建和使用。

 

但是,对于一个类,我们还有一些工作要做。提供构造函数和析构函数来完成类的创建和清理。

对于Stock类,也应提供构造函数和析构函数。

//stock.h  类的声明
#pragma once //防止头文件重复编译
#include<string>
 
class Stock   //类声明 class
{
private:  //私有成员 private
  std::string company; //公司名称,所持股票数量,每股价值,股票总值。
  long shares;
  double share_val;
  double total_val;
  void set_tot() { total_val = shares * share_val; }
public:   //公有成员,外部接口 public
//!!!!!!!!构造函数与析构函数!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  Stock();  //构造函数,名字与类名相同。
  Stock(const std::string & co, long n = 0, double pr = 0.0);//另一个构造函数(函数重载)
  ~Stock(); //(新手可略看)析构函数,使用完类 对类进行清理。
//功能函数----
  void buy(long num, double price); 
  void sell(long num, double price);
  void update(double price);
  void show()const;
};
//stock20.cpp stock类的具体实现
 
#include<iostream>
#include"stock.h"
 
Stock::Stock()
{
  std::cout << "默认构造函数\n";
  company = "no name";
  shares = 0;
  share_val = 0.0;
  total_val = 0.0;
}
 
Stock::Stock(const std::string & co, long n, double pr)
{
  std::cout << "构造函数使用 " << co << " 调用\n";
  company = co;
  if (n < 0)
  {
    std::cout << "shares 不能为负; "
      << company << ":shares 设置为0.\n";
    shares = 0;
  }
  else
    shares = n;
  share_val = pr;
  set_tot();
}
Stock::~Stock()
{
  std::cout << "Bye, " << company << '!\n';
}
 
void Stock::buy(long num, double price)
{
  if (num < 0)
  {
    std::cout << "shares 买入不能为负。"
      << "放弃操作。\n";
  }
  else
  {
    shares += num;
    share_val = price;
    set_tot();
  }
}
void Stock::sell(long num, double price)
{
  using std::cout;
  if (num < 0)
  {
    cout << "售出shares不能为负。"
      << "放弃售出操作。\n";
  }
  else if (num > shares)
  {
    cout << "售出不能大于所有。"
      << "放弃售出操作。\n";
  }
  else
  {
    shares -= num;
    share_val = price;
    set_tot();
  }
}
void Stock::update(double price)
{
  share_val = price;
  set_tot();
}
void Stock::show() const
{
  using std::cout;
  using std::ios_base;
  //此处为输出格式的设置,略看
  ios_base::fmtflags orig =
    cout.setf(ios_base::fixed, ios_base::floatfield);
  std::streamsize prec = cout.precision(3);
 
  cout << "公司:" << company
    << " 股份:" << shares << '\n'
    << "每股价格: $" << share_val;
  cout.precision(2);
  cout << " 总值: $" << total_val << '\n';
 
  //恢复原来的设置,避免影响其他输出。
  cout.setf(orig, ios_base::floatfield);
  cout.precision(prec);
}
 
 

加上了构造函数和析构函数后,Stock类变得更完整了。

 

接下来还可以Stock进行一些完善,比如给类添加一些方法,等等。

另外,对类也有一些操作,比如创建类的数组,使用指针,获取类的地址等等。类与之前的基本数据类型有很多相同的操作。

//stock20.h  类的声明
#pragma once //防止头文件重复编译
#include<string>
 
class Stock   //类声明 class
{
private:  //私有成员 private
  std::string company; //公司名称,所持股票数量,每股价值,股票总值。
  long shares;
  double share_val;
  double total_val;
  void set_tot() { total_val = shares * share_val; }
public:   //公有成员,外部接口 public
  Stock();  //构造函数,名字与类名相同。
  Stock(const std::string & co, long n = 0, double pr = 0.0);//另一个构造函数(函数重载)
  ~Stock(); //(新手可略看)析构函数,使用完类 对类进行清理。
  void buy(long num, double price); //功能函数
  void sell(long num, double price);
  void update(double price);
  void show()const;
  const Stock & topval(const Stock& s)const;//用来比较两个类,隐式传递this指针(指向调用函数的类)
};
//stock20.cpp stock类的具体实现
 
#include<iostream>
#include"stock20.h"
 
Stock::Stock()
{
  std::cout << "默认构造函数\n";
  company = "no name";
  shares = 0;
  share_val = 0.0;
  total_val = 0.0;
}
 
Stock::Stock(const std::string & co, long n, double pr)
{
  std::cout << "构造函数使用 " << co << " 调用\n";
  company = co;
  if (n < 0)
  {
    std::cout << "shares 不能为负; "
      << company << ":shares 设置为0.\n";
    shares = 0;
  }
  else
    shares = n;
  share_val = pr;
  set_tot();
}
Stock::~Stock()
{
  std::cout << "Bye, " << company << '!\n';
}
 
void Stock::buy(long num, double price)
{
  if (num < 0)
  {
    std::cout << "shares 买入不能为负。"
      << "放弃操作。\n";
  }
  else
  {
    shares += num;
    share_val = price;
    set_tot();
  }
}
void Stock::sell(long num, double price)
{
  using std::cout;
  if (num < 0)
  {
    cout << "售出shares不能为负。"
      << "放弃售出操作。\n";
  }
  else if (num > shares)
  {
    cout << "售出不能大于所有。"
      << "放弃售出操作。\n";
  }
  else
  {
    shares -= num;
    share_val = price;
    set_tot();
  }
}
void Stock::update(double price)
{
  share_val = price;
  set_tot();
}
void Stock::show() const
{
  using std::cout;
  using std::ios_base;
  //此处为输出格式的设置,略看
  ios_base::fmtflags orig =
    cout.setf(ios_base::fixed, ios_base::floatfield);
  std::streamsize prec = cout.precision(3);
 
  cout << "公司:" << company
    << " 股份:" << shares << '\n'
    << "每股价格: $" << share_val;
  cout.precision(2);
  cout << " 总值: $" << total_val << '\n';
 
  //恢复原来的设置,避免影响其他输出。
  cout.setf(orig, ios_base::floatfield);
  cout.precision(prec);
}
 
const Stock & Stock::topval(const Stock & s)const
{
  if (s.total_val > total_val)
    return s;
  else
    return *this;
}
 
#include<iostream>
#include"stock20.h"
 
const int STKS = 4;
int main()
{
 
  Stock stocks[STKS] =
  {
    Stock("NanoSmart",12,20.0),
    Stock("Boffo Objects",200,2.0),
    Stock("Monolithic Obelisks",130,3.25),
    Stock("Fleep Enter[rise",60,6.5)
  };
  std::cout << "持有股票:\n";
  for (int i = 0; i < STKS; i++)
  {
    stocks[i].show();
  }
  const Stock *top = &stocks[0];
  for (int i = 1; i < STKS; i++)
  {
    top = &top->topval(stocks[i]);
  }
  std::cout << "所持有的价值最高的是:\n";
  top->show();
  system("pause");
  return 0;
}


相关文章
|
4天前
|
安全 编译器 C++
C++一分钟之-模板元编程实例:类型 traits
【7月更文挑战第15天】C++的模板元编程利用编译时计算提升性能,类型traits是其中的关键,用于查询和修改类型信息。文章探讨了如何使用和避免过度复杂化、误用模板特化及依赖特定编译器的问题。示例展示了`is_same`类型trait的实现,用于检查类型相等。通过`add_pointer`和`remove_reference`等traits,可以构建更复杂的类型转换逻辑。类型traits增强了代码效率和安全性,是深入C++编程的必备工具。
24 11
|
8天前
|
设计模式 安全 编译器
【C++11】特殊类设计
【C++11】特殊类设计
27 10
|
13天前
|
C++
C++友元函数和友元类的使用
C++中的友元(friend)是一种机制,允许类或函数访问其他类的私有成员,以实现数据共享或特殊功能。友元分为两类:类友元和函数友元。类友元允许一个类访问另一个类的私有数据,而函数友元是非成员函数,可以直接访问类的私有成员。虽然提供了便利,但友元破坏了封装性,应谨慎使用。
41 9
|
8天前
|
存储 编译器 C语言
【C++基础 】类和对象(上)
【C++基础 】类和对象(上)
|
16天前
|
编译器 C++
【C++】string类的使用④(字符串操作String operations )
这篇博客探讨了C++ STL中`std::string`的几个关键操作,如`c_str()`和`data()`,它们分别返回指向字符串的const char*指针,前者保证以&#39;\0&#39;结尾,后者不保证。`get_allocator()`返回内存分配器,通常不直接使用。`copy()`函数用于将字符串部分复制到字符数组,不添加&#39;\0&#39;。`find()`和`rfind()`用于向前和向后搜索子串或字符。`npos`是string类中的一个常量,表示找不到匹配项时的返回值。博客通过实例展示了这些函数的用法。
|
16天前
|
存储 C++
【C++】string类的使用③(非成员函数重载Non-member function overloads)
这篇文章探讨了C++中`std::string`的`replace`和`swap`函数以及非成员函数重载。`replace`提供了多种方式替换字符串中的部分内容,包括使用字符串、子串、字符、字符数组和填充字符。`swap`函数用于交换两个`string`对象的内容,成员函数版本效率更高。非成员函数重载包括`operator+`实现字符串连接,关系运算符(如`==`, `&lt;`等)用于比较字符串,以及`swap`非成员函数。此外,还介绍了`getline`函数,用于按指定分隔符从输入流中读取字符串。文章强调了非成员函数在特定情况下的作用,并给出了多个示例代码。
|
21天前
|
C++
【C++】日期类Date(详解)②
- `-=`通过复用`+=`实现,`Date operator-(int day)`则通过创建副本并调用`-=`。 - 前置`++`和后置`++`同样使用重载,类似地,前置`--`和后置`--`也复用了`+=`和`-=1`。 - 比较运算符重载如`&gt;`, `==`, `&lt;`, `&lt;=`, `!=`,通常只需实现两个,其他可通过复合逻辑得出。 - `Date`减`Date`返回天数,通过迭代较小日期直到与较大日期相等,记录步数和符号。 ``` 这是236个字符的摘要,符合240字符以内的要求,涵盖了日期类中运算符重载的主要实现。
|
16天前
|
C++
【C++】string类的使用④(常量成员Member constants)
C++ `std::string` 的 `find_first_of`, `find_last_of`, `find_first_not_of`, `find_last_not_of` 函数分别用于从不同方向查找目标字符或子串。它们都返回匹配位置,未找到则返回 `npos`。`substr` 用于提取子字符串,`compare` 则提供更灵活的字符串比较。`npos` 是一个表示最大值的常量,用于标记未找到匹配的情况。示例代码展示了这些函数的实际应用,如替换元音、分割路径、查找非字母字符等。
|
16天前
|
C++
C++】string类的使用③(修改器Modifiers)
这篇博客探讨了C++ STL中`string`类的修改器和非成员函数重载。文章介绍了`operator+=`用于在字符串末尾追加内容,并展示了不同重载形式。`append`函数提供了更多追加选项,包括子串、字符数组、单个字符等。`push_back`和`pop_back`分别用于在末尾添加和移除一个字符。`assign`用于替换字符串内容,而`insert`允许在任意位置插入字符串或字符。最后,`erase`函数用于删除字符串中的部分内容。每个函数都配以代码示例和说明。
|
16天前
|
安全 编译器 C++
【C++】string类的使用②(元素获取Element access)
```markdown 探索C++ `string`方法:`clear()`保持容量不变使字符串变空;`empty()`检查长度是否为0;C++11的`shrink_to_fit()`尝试减少容量。`operator[]`和`at()`安全访问元素,越界时`at()`抛异常。`back()`和`front()`分别访问首尾元素。了解这些,轻松操作字符串!💡 ```