C++中基于对象的编程风格的学习,非常有难度,概念很抽象,操作起来也比较费脑子,这里主要把一些知识点和习题给过一遍!
一、前言
C++中基于对象的编程风格的学习(Essential C++ 第四章)。
二、例题
-P231 练习
一份“用户概况记录(user profle)”内含以下数据:登录记录、实际姓名、登入次数、猜过次数、精对次数、等级–包括初级、中级、高级、专家,以及猜对百分比(可实时计算获得,或称其值储存起来备用)。请写出一个名为 userprofile 的 class,提供以下操作:输入、输出、相等测试、不等测试。其 constructor 必须能够处理默认的用户等级,默认的登录名称("guest”),对于同样名为guest的多个用户,你如何保证每个guest有他自己独有的登录会话(login session),不会和其他人混淆?
- 先分析一下,一共有这几件事情要做:
-
- 一份“用户概况记录(user profle),其中包含:1 )登录记录、2)实际姓名、3)登入次数、4)猜过次数、5)猜对次数、6)等级–包括初级、中级、高级、专家,以及 7)猜对百分比);
-
- 一个名为 userprofile 的 class 提供以下操作:1)输入、2)输出、3)相等测试、4)不等测试;
-
- 构造函数(constructor) 必须能够处理默认的用户等级,默认的登录名称("guest”),对于同样名为guest的多个用户,要保证每个guest有他自己独有的登录会话(login session)。
#include <iostream>
#include <string>
#include <map>
using namespace std;class UserProfile {
public:enum uLevel { Beginner, Intermediate, Advanced, Guru };UserProfile(string login, uLevel = Beginner);UserProfile();// 重载 == 和 !=bool operator==(const UserProfile&);bool operator!=(const UserProfile& rhs);// 读取数据string login() const { return _login; }string user_name() const { return _user_name; }int login_count() const { return _time_logged; }int guess_count() const { return _guesses; }int guess_correct() const { return _correct_guesses; }double guess_average() const;string level() const;// 写入数据void reset_login(const string& val) { _login = val; }void user_name(const string& val) { _user_name = val; }void reset_level(const string&);void reset_level(uLevel newLevel) { _user_level = newLevel; }void reset_login_count(int val) { _time_logged = val; }void reset_guess_count(int val) { _guesses = val; }void reset_guess_correct(int val) { _correct_guesses = val; }// 这样写有什么好处吗?void bump_login_count(int cnt = 1) { _time_logged += cnt; }void bump_guess_count(int cnt = 1) { _guesses += cnt; }void bump_guess_correct(int cnt = 1) { _correct_guesses += cnt; }private:string _login;string _user_name;int _time_logged;int _guesses;int _correct_guesses;uLevel _user_level;static map<string, uLevel> _level_map;static void init_level_map();static string guest_login();};inline double UserProfile::guess_average() const
{return _guesses? double(_correct_guesses) / double(_guesses) * 100: 0.0;
}inline UserProfile::UserProfile(string login, uLevel level): _login(login), _user_level(level),_time_logged(1), _guesses(0), _correct_guesses(0) {}#include <cstdlib>inline UserProfile::UserProfile(): _login("guest"), _user_level(Beginner),_time_logged(1), _guesses(0), _correct_guesses(0)
{static int id = 0;char buffer[16];// itoa (C语言)将整数转换为对应的ASCII字符串 (C++)需要用 _itoa_S _itoa_s(id++, buffer, 10);_login += buffer;
}inline bool UserProfile::
operator==(const UserProfile &rhs)
{if ((_login == rhs._login) && (_user_name == rhs._user_name))return true;return false;
}inline bool UserProfile::
operator!=(const UserProfile &rhs)
{return !(*this == rhs);
}inline string UserProfile::level() const
{static string _level_table[] = {"Beginner","Intermediate","Advanced","Guru"};return _level_table[_user_level];}// 范例map<string, UserProfile::uLevel> UserProfile::_level_map;void UserProfile::init_level_map()
{_level_map["Beginner"] = Beginner;_level_map["Intermediate"] = Intermediate;_level_map["Advanced"] = Advanced;_level_map["Guru"] = Guru;
}inline void UserProfile::reset_level(const string& level)
{map<string, uLevel>::iterator it;if (_level_map.empty())init_level_map();_user_level =((it = _level_map.find(level)) != _level_map.end())? it->second : Beginner;}ostream& operator<<(ostream& os, const UserProfile& rhs)
{os << rhs.login() << ' ' << rhs.level() << ' ' << rhs.login_count() << ' '<< rhs.guess_count() << ' ' << rhs.guess_correct() << ' '<< rhs.guess_average() << endl;return os;
}istream& operator>>(istream& is, UserProfile& rhs)
{string login, level;is >> login >> level;int lcount, gcount, gcorrect;is >> lcount >> gcount >> gcorrect;rhs.reset_login(login);rhs.reset_level(level);rhs.reset_login_count(lcount);rhs.reset_guess_count(gcount);rhs.reset_guess_correct(gcorrect);return is;
}int main() {UserProfile anon;cout << anon;UserProfile anon_too;cout << anon_too;UserProfile anna("Anna", UserProfile::Guru);cout << anna;anna.bump_guess_count(27);anna.bump_guess_correct(25);anna.bump_login_count();cout << anna;cin >> anna;cout << anna;return 0;
}
- 这道题非常的赞哦,有三个非常重要的知识点:
- 1)
itoa (C语言)将整数转换为对应的ASCII字符串 (C++)需要用 _itoa_S
,避免重名,这个方法还不错。
-2)声明的函数一定要完成定义,否则报的错很让人脑壳痛。
代码是在 visual studio 中编写的,该软件还是比较好用的,我安装的是2022专业版;
共勉!