【问题标题】:Call non-static variable from a static function从静态函数调用非静态变量
【发布时间】:2016-02-12 19:40:06
【问题描述】:

我最近开始使用 C++,偶然发现了一个我似乎无法理解的问题。

class MyClass
{
    bool eventActive = false;

    static bool JoinCommand()
    {
        if (eventActive == true) // eventActive error: "a nonstatic member reference must be relative to a specific object"
        {
           // do something here...
        }
        else
        {

    }
};

我需要JoinCommand 是静态的,但我还需要使用eventActive,它必须是非静态的,并且由同一类中的其他函数使用/修改。因此我不能将 eventActive 设为静态,因为我还需要将其设为 const。

还有错误: “非静态成员引用必须相对于特定对象”

我想我无法创建MyClass 的新实例。那么我该怎么处理呢?或者有什么我不理解/我误解的错误?任何帮助将不胜感激。


编辑:

感谢大家帮助我解决这个问题。我完成了自己想要实现的目标,但在学习新事物时,我偶然发现了另一个与此类似的问题。

class Command
{
  public:
    const char *       Name;
    uint32             Permission;
    bool (*Handler)(EmpH*, const char* args); // I do not want to change this by adding more arguments
};
class MyClass : public CommandScript
{
 public:
  MyClass() : CommandScript("listscript") { }
  bool isActive = false;
  Command* GetCommands() const
  {
      static Command commandtable[] =
      {
          { "showlist", 3, &DoShowlistCommand } // Maybe handle that differently to fix the problem I've mentioned below?
      };
      return commandtable;
  }
  static bool DoShowlistCommand(EmpH * handler, const char * args)
  {
     // I need to use isActive here for IF statements but I cannot because
     // DoShowlistCommand is static and isActive is not static. 
     // I cannot pass it as a parameter either because I do not want to
     // change the structure of class Command at all

     // Is there a way to do it?
  }
};

【问题讨论】:

  • “我需要 JoinCommand 是静态的”,为什么。
  • 请阅读一本合理的关于静态的 C++ 教科书

标签: c++ function static instance non-static


【解决方案1】:

根据定义,类的静态成员函数独立于类的任何非静态成员的状态。这意味着您可以在没有对象的情况下使用它。

只要你依赖一个非静态成员,你的函数就必须是非静态的:

class MyClass
{
    bool eventActive = false;
public: 
    bool JoinCommand()           // non static, because 
    {
        if (eventActive == true) // it depends clearly on the state of the object
        { /* do something here... */ }
    }
};

然后您可以按预期调用您的成员函数:

MyClass omc; 
if (omc.JoinCommand()) 
     cout << "Command joined successfully"<<endl;  

如果您仍然有正当理由保持函数静态:

在静态成员函数中访问非静态元素的唯一方法是告诉函数它必须使用哪个对象来访问非静态(参数、全局对象等)。就像你在课堂之外所做的那样。

例子:

class MyClass
{
    bool eventActive = false;
public:
    static bool JoinCommand(MyClass& omc)  // example by provding a parameter
    {
        if (omc.eventActive == true)  // access non static of that object
        { /* do something here... */ }
    }
};

你可以这样称呼它:

MyClass obj; 
if (MyClass::JoinCommand(obj))    // a little bit clumsy, isn't it ? 
   ...

【讨论】:

  • 非常感谢您花时间解释它。我已经编辑了我的帖子,你能看看下面的问题吗?
  • @Chogart 您的编辑存在一些差异,值得专门单独回答。我建议您创建一个新问题(最终带有指向此问题的链接)。顺便说一句,这样做也会鼓励更多人回复
  • stackoverflow.com/questions/35414755/… 顺便说一句,我很感谢你的帮助,因为我对所有这些东西都是新手。
【解决方案2】:

如果您真的希望 JoinCommand 是一个静态方法,而 eventActive 是一个非静态成员,那么您唯一的选择就是将对象显式传递给该方法。

class MyClass
{
    bool eventActive = false;

    static bool JoinCommand(MyClass *object)
    {
        if (object->eventActive) // No error, since we are referencing through an object.
        {
           // do something here...
        }
        else
        {
           // Do something else here
        }
    }
};

【讨论】:

  • 可能最好将参数作为引用传递(const one?)以避免传递nullptr的可能性
  • @EdHeal,很公平,但考虑到问题的性质,我希望 OP 对 C 等语言有更好的理解,所以我希望指针对他来说比参考更熟悉.
【解决方案3】:

拥有非静态成员变量意味着 MyClass 的每个实例都有一个独立的 eventActive 成员,并且每个实例的值可以不同。这第二点意味着像“MyClass.eventActive”这样的东西没有任何意义。如果您有两个 MyClass 实例,并且 eventActive 的值在一个中为真,在另一个中为假,该怎么办?你指的是哪个值?如果您尝试创建一个只能有一个实例的类,您可能需要查看单例模式。即使在这种情况下,JoinCommand 也必须是非静态的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-10
    • 1970-01-01
    相关资源
    最近更新 更多