使用类和函数来跟踪用户统计信息
Posted
技术标签:
【中文标题】使用类和函数来跟踪用户统计信息【英文标题】:Using a class and functions to keep track of user stats 【发布时间】:2020-12-07 19:59:15 【问题描述】:我是 C++ 新手,想知道我做错了什么。
我正在尝试创建一个基于文本的冒险游戏,该游戏使用添加或删除功能来跟踪玩家统计数据。目前,我的函数没有为 trust
添加五个点,我正在努力做到这一点。
#include "function.h"
using namespace std;
int main()
double trust=100;
editPlayer user(100);
//asks user choice
cin >> firstChoice;
if (firstChoice == 1)
user.addTrust(trust);
cout << trust;
这是我的function.cpp
,仅以信任为例:
#include "function.h"
editPlayer::editPlayer(double trust)
void editPlayer::addTrust(double trust)
trust +=5;
void editPlayer::removeTrust(double trust)
trust -=5;
这是我的function.h
:
#include<iostream>
#include<string>
using namespace std;
class editPlayer
public:
editPlayer(double trust);
void addTrust(double);
void removeTrust(double);
;
【问题讨论】:
你用哪本书来学习C++?这不是类的使用方式。 【参考方案1】:让我们使用你的addTrust
函数:
void editPlayer::addTrust(double trust)
trust += 5;
这将修改局部变量trust
,然后函数将结束。当函数结束时,局部变量trust
的生命周期也结束了,你对它所做的修改也会丢失。
如果你真的想修改参数,你需要通过引用传递它:
void editPlayer::addTrust(double& trust)
trust += 5;
或者返回新值:
double editPlayer::addTrust(double trust)
return trust + 5;
如果返回新值,需要在调用函数时赋值给它:
trust = user.addTrust(trust);
如上所述,代码和editPlayer
类没有多大意义。真的不需要editUser
的课程。 addTrust
可能是一个非成员函数,或者根本不是一个函数。
类名没有意义,因为它不会“编辑”任何东西。并且将参数传递给构造函数也没有意义,因为对象没有任何内部状态(传递给构造函数的值只是被丢弃)。
【讨论】:
【参考方案2】:目前,您没有代表 user
对象(editPlayer
类的对象。
cout << trust;
语句仅打印您在开头声明的 trust
局部变量的值:double trust=100;
。因为这个变量自初始化以来一直没有改变,它仍然等于 100,这就是你所看到的。
为了跟踪任何editPlayer
特定的信息,最好的办法是将这些信息存储作为editPlayer
类的数据成员。您可以像这样声明一个表示对象的信任的数据成员:
class editPlayer
public:
editPlayer(double trust);
void addTrust(double);
void removeTrust(double);
double getTrust() const; // add also this one, will be useful
private:
double m_trust 0; // <---- here - a data member, aka. a class field
;
现在你必须改进你的构造函数,让它利用它所接受的参数并将它的值分配给这个新的数据成员(因为目前构造函数什么都不做):
editPlayer::editPlayer(double trust)
m_trust = trust;
现在在成员函数中,您已经重命名了变量,以便它反映 trust 数据成员(而不是参数),这将有效地允许更新其值:
void editPlayer::addTrust(double trust)
m_trust += 5;
void editPlayer::removeTrust(double trust)
m_trust -= 5;
double editPlayer::getTrust() const // add definition of our "getter"
return m_trust;
最后,您可以使用生成 m_trust
值的 getter 调用替换我们已经讨论过的 cout << trust;
(仍然打印局部变量的值):
cout << user.getTrust();
并查看执行addTrust()
操作的实际效果,并对您的合法面向对象程序感到满意。
【讨论】:
【参考方案3】:一般来说,您所询问的代码可以被类、成员声明以及一些面向对象编程所覆盖。 如果您搜索它,互联网上有很多好的(和不太好的)教程。
我会在以下搜索中试试运气
CPP + 课程 CPP + 成员声明 CPP + 动态与静态内存分配(指针和东西) 面向对象编程 (OOP)本网站上的示例提供了很多基本概念恕我直言的好(和短 :D)示例。 https://www.tutorialspoint.com/cplusplus/cpp_classes_objects.htm
其中一些主题也适用于其他语言。
我的 cmets 的第一个块:
#include "function.h"
using namespace std; // dont get into the habbit of using namespace std;
// the above can potentially open up for bugs
int main()
double trust=100; // This variable is declared in this scope( ... )
// and will get deallocated once the scope ends with the character ''
editPlayer user(100); // instance of editPlayer named 'user' is constructed
//asks user choice
cin >> firstChoice;
if (firstChoice == 1)
user.addTrust(trust); // calling function on user object
cout << trust;
现在查看 .h 文件,我主张不要在标头中包含您不使用的标头。 对于小型项目,这根本不重要 - 但对于包含数千行代码的大型项目,删除未使用的包含可以加快速度。
有些人更喜欢前向声明 - 一旦您对 cpp 的基础知识更加熟悉,就可以研究一下。
#include<iostream> // not used here
#include<string> // not used
using namespace std; // disaster waiting to happen
class editPlayer
public:
editPlayer(double trust);
void addTrust(double);
void removeTrust(double);
;
.cpp 文件
#include "function.h"
editPlayer::editPlayer(double trust)
// function implementation with argument - but argument is not used - change to void fun(double) -> fun(void) OR fun()
void editPlayer::addTrust(double trust) trust +=5;
void editPlayer::removeTrust(double trust) trust -=5;
我做了一个类声明和成员变量的例子。
#include <iostream>
#include <string>
// this is a class declaration
class Player
protected: // protected member variables
double _trust;
public: // public interface
Player(double trust);
void addTrust(double);
void removeTrust(double);
double getTrust() const;
;
// Implementation of public interface
// notice _trust is the member defined in the class
Player::Player(double trust) : _trust(trust) // constructor
// example of default parameters (do note that only definition or declaration can have them)
// This means that calling the function without arguments will become 5
void Player::addTrust(double trust = 5) _trust += trust;
void Player::removeTrust(double trust = 5) _trust -= trust;
double Player::getTrust() const return _trust;
int main()
Player player(100); // this will invoke the constructor - and the player object will get initialised with the given state
std::cout << player.getTrust() << std::endl;
// variable to buffer input data into - assuming type int wrt. following if
int firstChoice;
//asks user choice
std::cin >> firstChoice;
if (firstChoice == 1)
player.addTrust(25);
player.addTrust();
std::cout << player.getTrust();
编码愉快!
【讨论】:
const double getTrust();
- const
在返回的类型之前添加 按值 是无用的。可能你的意思是把这个 const
说明符放在 声明之后,使其成为 const 成员函数:double getTrust() const;
.
@bloody 是的,或者将其设为 const ref
@bloody 我做了这个实验——当返回类型为 const double& getTrust();成员变量仍然不是 const。我尝试运行以下几行 -> 首先是复制分配 double d = player.getTrust(); d += 1.0;
在没有 const 的情况下进行引用会产生编译错误。增加 const double const double &cd = player.getTrust(); cd += 1.0;
成员变量是什么意思?你的意思是成员函数,不是吗?
@bloody 我指的是我的 Player 类中的 protected: double _trust;
作为成员变量。以上是关于使用类和函数来跟踪用户统计信息的主要内容,如果未能解决你的问题,请参考以下文章
如何理解 Oracle 中跟踪文件的统计信息。如CPU、经过时间、查询...等
如何从手动创建的 Firebase 动态链接中收集统计信息?
R语言使用skimr包的skim_with函数自定义指定需要查看的统计信息统计口径查看dataframe特定数据列的summary信息统计汇总信息(Specify statistics)