【问题标题】: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++?这不是类的使用方式。

标签: c++ function class


【解决方案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 &lt;&lt; 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 &lt;&lt; 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 &amp;cd = player.getTrust(); cd += 1.0;
      • 成员变量是什么意思?你的意思是成员函数,不是吗?
      • @bloody 我指的是我的 Player 类中的 protected: double _trust; 作为成员变量。
      猜你喜欢
      • 2014-06-19
      • 1970-01-01
      • 2022-12-16
      • 2014-10-24
      • 1970-01-01
      • 2013-09-23
      • 2010-10-29
      • 2021-03-23
      • 1970-01-01
      相关资源
      最近更新 更多