J'ai lu quelques articles ici sur les fonctions statiques, mais j'ai toujours des problèmes d'implémentation.
J'écris un exemple codé en dur de l'algorithme de Dijkstra pour trouver le chemin le plus court.
Déclaré à Alg.h:
static void dijkstra();
Défini dans 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
Je veux appeler ma fonction depuis main sans objet . Quand j'ai eu tout ce code dans Main.cpp, cela a parfaitement fonctionné. Le fractionnement en fichiers séparés a provoqué l'erreur Main.cpp:15: error: ‘dijkstra’ was not declared in this scope
. Les messages que j'ai rencontrés lors de la recherche dans SE m'ont donné l'impression que pour ce faire, je devais rendre cette méthode statique, mais je n'ai toujours pas de chance.
Qu'est-ce que je fais mal?
Main.cpp:
#include <iostream>
#include "Alg.h"
int main() {
dijkstra();
return 0;
}
Edit: Ajout d'un fichier d'en-tête complet, 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
Fichier Main.cpp original tout-en-un fonctionnel: http://Pastebin.com/67u9hGsL
Vous devez l'appeler de cette façon:
Alg::dijkstra();
Limitations
new class()
lorsque le constructeur est privé/protégé. Par exemple. une fonction d'usine.Vous pouvez simplement utiliser un espace de noms au lieu d'avoir une classe avec tous les membres statiques.
Alg.h:
namespace Alg
{
void dijkstra();
}
et dans Alg.cpp
namespace Alg
{
void dijkstra()
{
// ... your code
}
}
dans main.cpp
#include "Alg.h"
int argc, char **argv)
{
Alg::dijkstra();
return 1;
}
Êtes-vous sûr que la fonction est censée être statique?
On dirait que vous voulez juste une fonction? dans votre fichier d'en-tête:
#ifndef DIJKSTRA_H
#define DIJKSTRA_H
void dijkstra();
#endif
dans votre fichier cpp
void dijkstra() {
/* do something */
}
dans votre fichier principal:
#include "yourcppfile.h"
int main(int argc, char **argv) {
dijkstra();
}
si vous voulez vraiment une fonction statique, vous devez la mettre dans une classe imbriquée:
class Alg {
public:
static void dijkstra();
/* some other class related stuff */
}
l'implémentation quelque part dans un fichier cpp
void Alg::dijkstra() {
/* your code here */
}
puis dans votre fichier cpp où réside le principal
#include "your header file.h"
int main(int argc, char **argv) {
Alg::dijkstra();
}
Si je me souviens bien, toute fonction "statique" est limitée au module dans lequel elle est implémentée. Ainsi, "statique" empêche d'utiliser la fonction dans un autre module.
Maintenant que nous avons la déclaration complète de votre classe Arg
, il semble que le modèle de conception singleton pourrait être utile:
Vous confondez le mot-clé "statique" pour les fonctions locales, avec le mot-clé "statique" utilisé dans une classe pour faire d'une fonction une fonction de classe et non une fonction d'objet.
Supprimez static
la première ligne d'Alg.cpp et dans le fichier d'en-tête. Cela permettra à Alg.o de contenir des symboles globaux auxquels main
peut se référer et que l'éditeur de liens peut lier.
Vous devez toujours appeler Alg::dijkstra()
comme indiqué par @egur.
Après cela, vous pouvez toujours obtenir des erreurs. La façon dont vous utilisez Alg :: ressemble plus à une définition de namespace
qu'à une définition de "classe".
Dans votre fichier d'en-tête Alg.h
:
#ifndef __ALG_H__
#define __ALG_H__
namespace Alg {
void dijkstra();
}
#endif
Les gardes d'inclusion sont nécessaires si vous prévoyez d'inclure l'en-tête dans plusieurs de vos fichiers cpp. Il semble que vous aimeriez mettre la fonction dans un espace de noms Alg
, non?
Dans Alg.cpp:
#include "Alg.h"
void Alg::dijkstra() { /* your implementation here */ }
Ensuite, dans main.cpp, vous l'appelez avec la qualification complète de l'espace de noms:
#include "Alg.h"
int main() {
Alg::dijkstra();
}
Si vous voulez juste distribuer votre code sur plusieurs fichiers, je ne vois pas pourquoi la fonction devrait être déclarée static
.
La clé ici est le ‘dijkstra’ was not declared in this scope
Erreur.
Prenez votre fichier source tout-en-un et supprimez la fonction main
. Créez un nouveau fichier source avec ceci:
void dijkstra();
void output();
int main(int argc, char *argv[]) {
dijkstra();
output();
return 0;
}
Le cpp tout-en-un sans main
plus ce fichier ci-dessus devrait compiler ensemble et vous donner le même résultat qu'auparavant avec une source, comme pour moi. Vous obtiendrez un duplicate symbol _main
erreur si vous avez oublié de supprimer le fichier principal du fichier d'algorithme.
Aucun static
nécessaire.
Ma réponse ici ne touche pas aux bonnes pratiques sur les fichiers d'en-tête, c'est-à-dire que vous voudriez inclure ces déclarations de fonction dans un .h
fichier. Il résout cependant l'erreur de compilation.
Vous voudrez peut-être trouver un bon livre pour vous aider à travers certaines des machines de C++, où le contexte du programme (au sens linguistique) peut changer la signification des mots-clés. Cela peut être déroutant, et il s'avère que c'est exactement le cas pour un langage avec autant d'histoire colorée que C++. Jetez un oeil ici pour des suggestions de livres.