Статические функции в С++
Я прочитал несколько сообщений здесь о статических функциях, но все равно сталкиваюсь с проблемами с реализацией.
Я пишу 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
. Однако он решает ошибку времени компиляции.
Возможно, вам захочется найти хорошую книгу, которая поможет вам через некоторые из механизмов С++, где контекст программы (в лингвистическом смысле) может изменить значение ключевых слов. Это может быть сбивающим с толку, и это оказывается именно тем, что для языка с такой же красочной историей, как С++. Посмотрите здесь для предложений по книге.