C++中的静态函数

22

我在这里读到了一些有关静态函数的帖子,但是在实现上仍然遇到了问题。

我正在编写Dijkstra算法的硬编码示例,用于找到最短路径。

在Alg.h中声明:

static void dijkstra();

在 Alg.cpp 中定义:

static void Alg::dijkstra() { 

//Create Map
Initialize();

//Loop to pass through grid multiple times
for(int i=0; i<5; i++)
{   
    current=1;  
    while(current!=6)
    {
        //Iterate through and update distances/predecessors
        //For loop to go through columns, while current iterates rows
        for(int j=1; j<7; j++)
        {
            //Check if distance from current to this node is less than
            //distance already stored in d[j] + weight of edge

            if(distanceArray[current][j]+d[current]<d[j])
            {
                //Update distance
                d[j] = distanceArray[current][j]+d[current];
                //Update predecessor
                p[j] = current;
            }    
        }
        //Go to next row in distanceArray[][]
        current++;
    } //End while


} //End for

output();
} //End Dijkstras

我希望从主函数中无需对象调用我的函数。当我把所有代码放在Main.cpp中时,它能够完美运行。但是将其拆分为单独的文件导致错误Main.cpp:15: error: ‘dijkstra’ was not declared in this scope。搜索SE时看到的帖子让我觉得,要做到这一点,我需要将该方法设为静态,但我仍然没有成功。
我做错了什么?
Main.cpp:
#include <iostream>
#include "Alg.h"

int main() { 

    dijkstra();
    return 0; 
}

编辑:添加完整的头文件Alg.h:

#ifndef Alg_
#define Alg_

#include <iostream>
#include <stack>

using namespace std;

class Alg
{
    public:
        void tracePath(int x);
        void output();
        void printArray();
        void Initialize();
        static void dijkstra();
        int current, mindex;
        int distanceArray[7][7]; //2D array to hold the distances from each point to all others
        int d[6]; //Single distance array from source to points
        int p[6]; //Array to keep predecessors 
        int copyD[6]; //Copy of d[] used for sorting purposes in tracePath()
        int order[6]; //Contains the order of the nodes path lengths in ascending order

}; //End alg class

#endif

原始的全功能工作的Main.cpp文件:http://pastebin.com/67u9hGsL


3
请提供您的头文件完整上下文。我猜测 dijkstra 应该是一个类静态成员? - CB Bailey
1
静态成员函数的定义不能包含关键字“static”。你试图定义static void Alg::dijkstra() {将立即在Alg.cpp中触发编译错误。然而,你报告了一个完全不同的错误。并且你声称这段代码在main.cpp中“工作”。这意味着你发布了虚假的代码。你的说法是不现实的。请发布真实的代码。 - AnT stands with Russia
Alg是什么?它是一个类吗?还是一个命名空间? - AnT stands with Russia
@AndreyT Alg 是一个类。请查看编辑。 - Ladybro
1
@user3063527:嗯...你在pastebin上链接的代码与问题完全不同。那段代码中没有Alg,也没有static - AnT stands with Russia
显示剩余3条评论
8个回答

29

你应该这样调用它:

Alg::dijkstra();

局限性

  • 无法调用任何非静态的类函数。
  • 无法访问非静态类数据成员。
  • 可以通过new class()来实例化一个私有/受保护的构造函数。例如工厂函数。

@Johnsyweb 这让我遇到了一个“无法在没有对象的情况下调用成员函数”的错误。 - Ladybro
2
也许 Initialize() 不是一个静态函数?你不能从静态函数中调用实例函数,因为你没有从“内部”对象中调用它。 - SJuan76
很有可能Alg是一个命名空间而不是一个类... 然而,提问者仍然没有解释Alg到底是什么。 - AnT stands with Russia
@egur 谢谢,现在更有意义了。 - Ladybro

10

你可以只使用命名空间而不是拥有所有静态成员的类。

Alg.h:

namespace Alg
{
   void dijkstra();
}

以及在 Alg.cpp 中。

namespace Alg
{
   void dijkstra()
   {
     // ... your code
   }
}

在 main.cpp 文件中

#include "Alg.h"

int argc, char **argv)
{
  Alg::dijkstra();

  return 1;
}

6

您确定该函数应该是静态的吗?

看起来你只需要一个函数? 在你的头文件中:

#ifndef DIJKSTRA_H
#define DIJKSTRA_H
void dijkstra(); 
#endif

在你的cpp文件中

void dijkstra() {
   /* do something */
}

在你的主文件中:
#include "yourcppfile.h"

int main(int argc, char **argv) {
    dijkstra();
}

如果您真的想要一个静态函数,您需要将其放入嵌套类中:

class Alg {
  public:
    static void dijkstra();
  /* some other class related stuff */
}

在cpp文件中执行的实现

void Alg::dijkstra() {
  /* your code here */
}

然后在您的 CPP 文件中,其中包含主函数

#include "your header file.h"

int main(int argc, char **argv) {
  Alg::dijkstra();
}

3
如果我没记错的话,任何“静态”函数都被限制在它所实现的模块内。因此,“静态”会防止在另一个模块中使用该函数。

2
在您的头文件Alg.h中:
#ifndef __ALG_H__
#define __ALG_H__

namespace Alg {

    void dijkstra();

}

#endif

如果你计划在多个cpp文件中包含头文件,则需要使用包含保护。看起来你想将函数放在名为Alg的命名空间中,是吗?
在Alg.cpp文件中:
#include "Alg.h"

void Alg::dijkstra() { /* your implementation here */ }

然后,在 main.cpp 中,您可以通过完整的命名空间限定符调用它:

#include "Alg.h"

int main() {

    Alg::dijkstra();

}

如果你只是想将你的代码分布在几个文件中,我不明白为什么这个函数应该被声明为 static

0

这里的关键是出现了‘dijkstra’ was not declared in this scope错误。

将您的全能源文件中的main函数删除。创建一个新的源文件,并在其中添加以下内容:

void dijkstra();
void output();

int main(int argc, char *argv[]) {
    dijkstra();
    output();
    return 0;
}

这个全能的cpp文件没有main函数,加上上面的文件应该一起编译,给你一个源文件的结果和之前一样,对我来说也是如此。如果你忘记从算法文件中删除main函数,你会得到一个duplicate symbol _main错误。

不需要static


我的回答没有涉及头文件的良好实践,也就是说,您希望将这些函数声明包含在一个.h文件中。虽然它可以解决编译时错误。

您可能想找一本好书来帮助您了解C++的一些机制,其中程序上下文(从语言学意义上讲)可以改变关键字的含义。这可能令人困惑,对于像C++这样具有丰富历史的语言来说,确实如此。请查看这里以获取书籍建议。


谢谢您的帮助,我会查看您发布的内容。 - Ladybro

0

你把“static”关键字用于局部函数和用于类中将函数定义为类函数而不是对象函数的含义混淆了。

在Alg.cpp文件的第一行和头文件中删除static。这将允许Alg.o包含全局符号,以便main可以引用并且链接器可以链接。

你仍然需要像@egur所说的那样调用Alg::dijkstra()

完成上述步骤后,你可能仍会遇到错误。你使用Alg::的方式更像是一个namespace而不是“class”定义。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接