stock00.h
#pragma once
//10.1 stock00.h -- Stock class inter face
//version 00
#ifndef STOCK00_H_
#define STOCK00_H_
#include<string>
class Stock
{
private:
std::string company;
long shares; //持有的股票支数
double share_val; //持有股票单价
double total_val; //持有股票总值
void set_tot() { total_val = shares * share_val; } //设置total_val
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();
};
#endif // !STOCK00_H_
stock00.cpp
//stock00.cpp -- implementing the Stock class
//version 00
#include<iostream>
#include "stock00.h"
void Stock::acquire(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_tot();
}
void Stock::buy(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_tot();
}
}
void Stock::sell(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_tot();
}
}
void Stock::update(double price)
{
share_val = price;
set_tot();
}
void Stock::show()
{
std::cout << "Company: " << company
<< " Shares: " << shares << '\n'
<< " Share Price: $" << share_val
<< " Total Worth: $" << total_val << '\n';
}
stock10.h
#pragma once
#ifndef STOCK10_H_
#define STOCK10_H_
#include<string>
#include<iostream>
//下面将构造函数和析构函数加入到类和方法的定义中
//鉴于添加构造函数的重大意义,这里将名称从stock00.h->stock10.h
class Stock
{
private:
std::string company;
long shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
Stock(); //默认构造函数
/*也可以定义为Stock(const string &co="Error",int n=0,double pr=0.0)
这是默认构造函数的唯二两种定义方式
为类定义了构造函数后,程序员就必须为它提供默认构造函数
如果提供了非默认构造函数但没有提供默认构造函数
则创建类对象的声明将会出错*/
//为类定义了构造函数
Stock(const std::string& m_company, long m_shares = 0, double m_share_val = 0.0);
~Stock() { std::cout << "Bye-bye," << company << "!\n"; }
//析构函数,一般将它编写为不执行任何操作的函数
//此处是为了让您看出析构函数何时被调用
/*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();
};
#endif // !STOCK10_H_
stock10.cpp
#include "stock10.h"
Stock::Stock()
{
std::cout << "Default constructor called\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 << "Constructor using " << co << " called\n";
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_tot();
}
void Stock::buy(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_tot();
}
}
void Stock::sell(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_tot();
}
}
void Stock::update(double price)
{
share_val = price;
set_tot();
}
void Stock::show()
{
using std::cout;
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 << "Company: " << company
<< " Shares: " << shares << '\n';
cout << "Share Price: $" << share_val;
//set format to #.##
cout.precision(2);
cout << " Total Worth: $" << total_val << '\n';
//restore original format
cout.setf(orig, ios_base::floatfield);
cout.precision(prec);
}
usestock1.cpp
#include "stock10.h"
int main()
{
//如果没有这些大括号,代码块将为整个main(),因此仅当main()执行完毕后,才会调用析构函数
//在窗口环境中,这意味着将在两个析构函数调用前关闭,导致您无法看到最后两条信息
//添加这些大括号后,最后两个析构函数调用将在到达返回语句前执行,从而显示相应的信息
{
using std::cout;
cout << "Using constructors to create new objects\n";
//两种使用构造函数来初始化对象的方式
//隐式地调用构造函数
Stock stock1("NanoSmat", 12, 20.0); //syntax 1
stock1.show();
//显式地调用构造函数
Stock stock2 = Stock("Boffo Objects", 2, 2.0); //syntax 2
stock2.show();
cout << "Assigning stock1 to stock2:\n";
stock2 = stock1;
cout << "Listing stock1 and stock2:\n";
stock1.show();
stock2.show();
cout << "Using a constructor to reset an object\n";
stock1 = Stock("Nifty Foods", 10, 50.0); //temp object
//stock1对象已经存在,因此这条语句不是对stock1进行初始化,而是将新值赋给它
//这是通过让构造程序创建一个新的、临时的对象,然后将其内容复制给stock1来实现
//随后程序调用析构函数,以删除该临时对象
//故输出如下所述: Constructor using Nifty Foods called
// Bye - bye, Nifty Foods!
//初始化语句与赋值语句有着根本性的差别,且初始化的方式效率更高
cout << "Revised stock1:\n";
stock1.show();
cout << "Done\n";
}
return 0;
}
/*
Using constructors to create new objects
Constructor using NanoSmat called
Company: NanoSmat Shares: 12
Share Price: $20.000 Total Worth: $240.00
Constructor using Boffo Objects called
Company: Boffo Objects Shares: 2
Share Price: $2.000 Total Worth: $4.00
Assigning stock1 to stock2:
Listing stock1 and stock2:
Company: NanoSmat Shares: 12
Share Price: $20.000 Total Worth: $240.00
Company: NanoSmat Shares: 12
Share Price: $20.000 Total Worth: $240.00
Using a constructor to reset an object
Constructor using Nifty Foods called
Bye-bye,Nifty Foods!
Revised stock1:
Company: Nifty Foods Shares: 10
Share Price: $50.000 Total Worth: $500.00
Done
Bye-bye,NanoSmat!
Bye-bye,Nifty Foods!
*/
//由于这种自动变量被放在栈中,因此最后创建的对象将最先被删除,最先创建的对象将最后被删除
stock20.h
#pragma once
//增加了const成员函数和this指针
/*
const Stock land=Stock("Kludgehorn Properies")
land.show()
对于当前的C++来说,编译器将拒绝第二行,因为show()的代码无法确保调用对象不被修改
需要一种新的语法——保证函数不会修改调用对象
C++的解决方法是将const关键字放在函数的括号后面。
也就是说,show()声明应像这样:
void show() const; //promises not to change invoking object
同样,函数定义的开头应像这样:
void stock::show() const //promises not to change invoking object
只要类方法不修改调用对象,就应将其声明为const
从现在开始,我们将遵守这一规则
*/
/*
有时候方法可能涉及到两个对象,在这种情况下需要使用C++的this指针
每个成员函数(包括析构函数和构造函数)都有一个this指针
this指针指向调用对象
如果方法要引用整个调用对象,则可以使用表达式*this
*/
#ifndef STOCK20_H_
#define STOCK20_H_
#include<string>
class Stock
{
private:
std::string company;
long shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
Stock();
Stock(const std::string m_company, long m_shares=0, double m_share_val=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;
/*该函数隐式地访问一个对象,而显示地访问另一个对象,并返回其中一个对象的引用
括号中的const表明,该函数不会修改被显示地访问的对象
而括号后地const表明,该函数不会修改被隐式地访问的对象
由于该函数返回了两个const对象之一的引用,因此返回类型也应为const引用*/
};
#endif // !STOCK20_H_
stock20.cpp
#include<iostream>
#include "stock20.h"
//constructors
Stock::Stock()
{
company = "no name";
shares = 0;
share_val = 0.0;
total_val = 0.0;
}
Stock::Stock(const std::string m_company, long m_shares, double m_share_val)
{
std::cout << "Constructor using " << m_company << " called\n";
company = m_company;
if (m_shares < 0)
{
std::cout << "Number of shares can't be negative;"
<< company << "shares set to 0\n";
shares = 0;
}
else
{
shares = m_shares;
}
share_val = m_share_val;
set_tot();
}
Stock::~Stock()
{
}
void Stock::buy(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_tot();
}
}
void Stock::sell(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_tot();
}
}
void Stock::update(double price)
{
share_val = price;
set_tot();
}
void Stock::show() const
{
using std::cout;
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 << "Company: " << company
<< " Shares: " << shares << '\n';
cout << "Share Price: $" << share_val;
//set format to #.##
cout.precision(2);
cout << " Total Worth: $" << total_val << '\n';
//restore original format
cout.setf(orig, ios_base::floatfield);
cout.precision(prec);
}
const Stock& Stock::topval(const Stock& s) const
{
if (s.total_val > this->total_val)
return s;
else
return *this;
}
usestock2.cpp
#include<iostream>
#include "stock20.h"
const int STKS = 4;
int main()
{
//create an array of initialized objects
Stock stocks[STKS] = {
Stock("NanoSmart",12,20.0),
Stock("Boffo Objects",200,2.0),
Stock("Monolithic Oberlisks",130,3.25),
Stock("Fleep Enterprises",60,6.5)
};
std::cout << "Stock hodings:\n";
int st;
for (st = 0; st < STKS; st++)
{
stocks[st].show();
}
const Stock* top = &stocks[0];
/*
* 指针和const,可以用两种不同的方式将const关键字用于指针
* 第一种方法是让指针指向一个常量对象,这样可以防止使用该指针来修改所指向的值
* 第二种方法是将指针本身声明为常量,这样可以防止改变指针指向的位置
* 此处声明用的是第一种方法,top指向一个const Stock,因此不能用top来修改这个值
*/
for (st = 1; st < STKS; st++)
{
top = &(top->topval(stocks[st]));
}
std::cout << "\nMost valuable holding:\n";
top->show();
return 0;
}
/*
Constructor using NanoSmart called
Constructor using Boffo Objects called
Constructor using Monolithic Oberlisks called
Constructor using Fleep Enterprises called
Stock hodings:
Company: NanoSmart Shares: 12
Share Price: $20.000 Total Worth: $240.00
Company: Boffo Objects Shares: 200
Share Price: $2.000 Total Worth: $400.00
Company: Monolithic Oberlisks Shares: 130
Share Price: $3.250 Total Worth: $422.50
Company: Fleep Enterprises Shares: 60
Share Price: $6.500 Total Worth: $390.00
Most valuable holding:
Company: Monolithic Oberlisks Shares: 130
Share Price: $3.250 Total Worth: $422.50
*/