Статические функции в С++

Я прочитал несколько сообщений здесь о статических функциях, но все равно сталкиваюсь с проблемами с реализацией.

Я пишу hardcoded пример алгоритма Дейкстры для поиска кратчайшего пути.

Объявлено в 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 all-in-one: http://pastebin.com/67u9hGsL

Ответ 1

Вы должны называть это следующим образом:

Alg::dijkstra();

Ограничения

  • Невозможно вызвать любые другие функции класса, которые не являются статическими.
  • Невозможно получить доступ к элементам нестатического класса.
  • Может создавать объект через new class(), когда конструктор является приватным/защищенным. Например. a factory.

Ответ 2

Вы уверены, что функция должна быть статической?

Похоже, вы хотите только функцию? в файле заголовка:

#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

Вы можете просто использовать пространство имен вместо того, чтобы иметь класс со всеми статическими членами.

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;
}

Ответ 4

Если я правильно помню, любая "статическая" функция ограничивается модулем, в котором она реализована. Таким образом, "статический" предотвращает использование функции в другом модуле.

Ответ 5

Вы смешиваете ключевое слово "static" для локальных функций с ключевым словом "static", используемым в классе, чтобы сделать функцию функцией класса, а не функцией объекта.

Удалите static первую строку файла Alg.cpp и в файл заголовка. Это позволит Alg.o содержать глобальные символы, на которые main может ссылаться, и компоновщик может ссылаться.

Вам все равно нужно позвонить Alg::dijkstra(), как было указано в @egur.

После этого вы все равно можете получить ошибки. То, как вы используете Alg:: больше похоже на namespace, чем определение класса.

Ответ 6

В файле заголовка 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.

Ответ 7

Теперь, когда у нас есть полное объявление вашего класса Arg, похоже, что шаблон дизайна singleton может быть полезным:

http://en.wikipedia.org/wiki/Singleton_pattern

Ответ 8

Ключ здесь - ошибка ‘dijkstra’ was not declared in this scope.

Возьмите исходный файл "все-в-одном" и удалите функцию main. Создайте в нем новый исходный файл:

void dijkstra();
void output();

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

Компонент "все-в-одном" без main плюс этот файл выше должен скомпилироваться вместе и дать вам тот же результат, что и раньше, с одним источником, как и для меня. Вы получите ошибку duplicate symbol _main, если забыли удалить основной файл алгоритма.

Нет static.


Мой ответ здесь не затрагивает хорошие практики в файлах заголовков, то есть вы хотели бы включить эти объявления функций в файл .h. Однако он решает ошибку времени компиляции.

Возможно, вам захочется найти хорошую книгу, которая поможет вам через некоторые из механизмов С++, где контекст программы (в лингвистическом смысле) может изменить значение ключевых слов. Это может быть сбивающим с толку, и это оказывается именно тем, что для языка с такой же красочной историей, как С++. Посмотрите здесь для предложений по книге.