从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; }