【问题标题】:C++ When should a function/ call be static/ non-static?C++ 函数/调用何时应该是静态/非静态的?
【发布时间】:2014-11-07 09:58:28
【问题描述】:

我在名为spiral.cpp 的C++ 源文件中定义了一个函数,我正试图从另一个名为manager.cpp 的C++ 源文件中调用该函数。但是,我收到一个编译错误,上面写着“非法调用非静态成员函数”。

我已经查看了出现此编译错误的原因,到目前为止我发现的所有内容似乎都告诉我,我需要在其定义中创建函数 static。但是,如果我这样做,则会收到一个编译错误,提示“不应在文件范围内定义的成员函数上使用'static'”。

函数在spiral.cpp中定义,代码为:

int spiralItem::updateCircuitNumber(void){
    ...
}

然后在manager.cpp 中调用它:

spiral::updateCircuitNumber();

谁能向我解释我在这里做错了什么?问题肯定与函数被错误地定义/调用为静态/非静态有关,还是其他原因?

【问题讨论】:

  • 您确定要使用静态函数吗?至少名称暗示您正在操纵状态(spiral 实例(?))
  • 不-我不确定我是否想要一个静态函数...这就是我问这个问题的原因...编译器告诉我某些东西需要是静态的-无论它是函数定义/调用/两者 - 我不确定。我真的不明白 static 是什么/做什么...

标签: c++ static function-declaration


【解决方案1】:

正如我在评论中提到的,您的函数名称让我假设您实际上想要操纵特定 spiral 实例的状态。在这种情况下,您将需要(或至少通常使用)一个 member 函数。看来这就是您实际所做的。查看。 现在,为了调用这个函数,你需要有一个spiral 的实例,你可以在上面调用这个函数。

spiral s;
s.updateCircuitNumber();

或(如果动态分配)

spiral * s = new spiral();  // better use appropriate smart_ptr but that's another story
s->updateCircuitNumber();

这些调用会更改特定sobject 的状态。如果您有另一个spiralobject s2,则保持不变,您可以根据需要随时为该实例调用updateCircuitNumber()非静态成员函数也称为实例函数,因为它们对类的特定实例进行操作。

static 函数也称为类函数,因为它们独立于该类的特定实例。因此,它们只能访问该类的静态成员,而不能访问非静态成员(因为这些仅存在于不可用的特定实例中)。如其他答案中所述,static 关键字仅添加在类声明中。然后可以在您尝试使用 spiral::updateCircuitNumber(); 时调用静态函数。

【讨论】:

  • 这是正确的——我确实想操纵特定螺旋实例的状态。我尝试通过创建spiral 的实例并在该实例上调用函数来执行此操作:spiralItem newSpiral = new spiralItem();newSpiral::updateCircuitNumber();,但这给了我三个错误:1.“'initializing': cannot convert from 'spiralItem *'到 'spiralItem'"... 我看不到我在哪里使用它在这里提到的指针... 2. "'newSpir​​al' : left of '::' must be class/struct/union", 3. "'updateCircuitNumber' : 未找到标识符"...
  • 如果你动态分配,你会得到一个指针,所以你需要声明spiralitem * newSpiral...(见我的回答)。要在该实例上调用该函数,您需要使用-> 运算符(或. 用于堆栈上的对象)在该实例上newSpiral->updateCircuitNumber();,如我上面的回答中所述。
  • 太棒了,已经成功了——非常感谢!
【解决方案2】:

您必须在类声明中使用static,但在函数定义中不能

class spiralItem
{
...
public:
    static int updateCircuitNumber(void);
};

spiral.cpp:

int spiralItem::updateCircuitNumber(void){
    ...
}

你调用manager.cpp中的函数:

spiralItem::updateCircuitNumber();

简单地把这当作C++的规则;乍一看确实有点奇怪。

【讨论】:

  • 嘿,谢谢你的回答-我已经尝试过了-所以我现在有了spiralItem.cpp中定义的函数:int spiralItem::updateCircuitNumber(void){...},并在manager.cpp中调用它@ 987654330@,但我现在在manager.cpp 的行上收到一个编译错误,上面写着“不允许重新声明成员函数”......知道这是为什么吗?
  • 从函数调用中删除static,并使用类名spiralItem(虽然可以,但不需要使用类的实例)。
  • 我已经这样做了,但我收到一条错误消息,提示“不允许重新声明成员函数”。目前,该函数在spiralItem.cpp 中声明为:int spiralItem::updateCircuitNumber(void){...},并在manager.cpp 中以int spiralItem::updateCircuitNumber(); 调用。我看不出这是如何重新声明函数...?
  • int spiralItem::updateCircuitNumber(); 不是调用函数。
【解决方案3】:

你可以在一个类中拥有静态成员函数。这里首先要注意的是静态成员函数没有这个指针,这意味着你不能在静态函数中访问类的任何数据成员/非静态成员函数,因为它们需要这个指针。第二点是静态成员函数可以是在没有实例化类的情况下调用。

例如:-

class One
{
private:
   static int count;
public:
  static int getCount ()
  {
    return count;
  }
};

您必须在 .cpp 文件中初始化计数:-

int One::count = 0;

然后你可以像这样调用成员函数:-

std::cout << One::getCount () << std::endl;

【讨论】:

    【解决方案4】:

    您的错误可能在头文件中。你如何声明你的静态方法?

    考虑到您的示例,它应该是这样的:

    class spiralItem {
    public:
      static int updateCircuitNumber(void);
    };
    

    【讨论】:

    • 我已经在头文件中声明了函数:int updateCircuitNumber(void);。我现在应该将此声明设为静态吗?
    • 您应该像我的示例所示那样声明它。 static 关键字只出现在头文件中。static 关键字也只出现在类声明中,不适用于全局函数。
    猜你喜欢
    • 2013-11-10
    • 1970-01-01
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多