【问题标题】:How to run a non-static function in a new thread in C++如何在 C++ 的新线程中运行非静态函数
【发布时间】:2018-09-12 00:49:54
【问题描述】:

我正在尝试用 C++ 编写一个基本游戏。我有一个名为 player 的类,它有一个名为 moveLeft(); 的函数,它不断监控我想在单独的线程中运行的“a”get。

按照我的想法来称呼它。我现在明白这是因为它是一个非静态函数,但我现在不确定如何执行此操作。我正在使用 库。

播放器类

#pragma once
class player
{
    public:
        player(); // Constructor
        ~player(); // Destructor

        void moveLeft();
        void moveRight();
        void jump(double);

        int getHealth();

        double get_x_position();
        double get_y_position();

        double get_x_momentum();
        double get_y_momentum();

        bool getGrounded();

        void setHealth(int);

        void set_x_position(double);
        void set_y_position(double);

        void set_x_momentum(double);
        void set_y_momentum(double);

        void setGrounded(bool);

    private:
        int health;

        bool grounded;

        double x_position;
        double y_position;

        double x_momentum;
        double y_momentum;
};

moveLeft() 函数

void player::moveLeft()
{
    while (true)
    {
        while (GetKeyState(97))
        {
            if (grounded)
            {
                x_momentum -= .01;
            }
            else
            {
                x_momentum -= 0.07;
            }

            x_position += x_momentum;
        }
    }
}

我认为我应该如何设置它。

thread t1(&player::moveLeft);
t1.detach();

【问题讨论】:

  • 使用静态函数启动线程并将player作为参数传递给它:thread t1(&run, player);在run 函数中调用player->moveLeft()

标签: c++ multithreading class non-static


【解决方案1】:

如果您从类的成员函数启动线程,您可能正在寻找

thread t1(&player::moveLeft, this);
t1.detach();

包含this 指针的原因是每个成员函数都有一个隐藏参数,即指向与其关联的对象的指针。上面代码中的thisplayer*。当然,您可以使用任何其他指向player 的指针,不一定是this。无论您指向什么对象,成员函数都会在其主体内将其视为“此对象”。

【讨论】:

  • 谢谢!但是现在当我运行它时,我得到了这个错误“E0258 'this' may only be used inside a nonstatic member function”
  • 所以你是从静态成员函数启动线程?这些函数看不到this 指针,它们就像类命名空间中的全局函数。它不会以这种方式工作。您可能需要重新评估您的程序架构。
【解决方案2】:

如果你想这样做,你需要创建一个播放器类的实例

player *myplayer = new player(); //do this in your initializer, not for every call.
thread t1(&player::moveLeft, myplayer);
t1.detach();

如果您只想要一个播放器实例,则在另一个回复中发布的单例方法将起作用。

【讨论】:

    【解决方案3】:

    你可以使用std::bind来解决这个问题。

    thread t1(std::bind(&player::moveLeft,this));
    t1.detach();
    

    【讨论】:

    • 随着 lambda 的出现,std::bind 的使用基本上已被弃用。
    • 感谢您的提醒。所以让我们使用 lambda 来处理它。线程 t1([&]() { player.moveLeft(); } ); t1.detach();
    • std::bind()不是必须的,线程的构造函数可以直接带this参数。
    【解决方案4】:

    恕我直言 - 我认为您的程序结构或总体设计不合适。

    • 您不应在问题域对象的方法中进行事件处理或 I/O 处理。
    • 如果对何时发生移动有限制(例如,在发生某些事情之前不要向左移动) - 为什么要公开哪些方法会立即影响移动(例如 set_x_position())?
    • 如果您有一些微不足道的 getter 和 setter,为什么还要打扰他们呢?难道你真的不应该放弃 setter 吗?
    • 播放器类实例在多个线程之间共享。当您在其中一个中更改它时,您不应该以某种方式锁定它吗?

    不过,要回答您的具体问题:

    auto l = [&]() { player1.moveLeft(); }
    auto t1 = std::thread{l};
    t1.detach();
    

    【讨论】:

    • 谢谢。抱歉,我知道我的代码不是最好的。我刚开始学习类和对象,所以我需要一点时间来掌握它。
    • @diego_rod:无需道歉——我们一直在 StackOverflow 上看到这一点。重要的是你提问得当(你似乎有),而不是你有经验或有好的代码和好的设计。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-09
    • 2016-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 2011-07-18
    相关资源
    最近更新 更多