web-dev-qa-db-fra.com

Fonctions statiques en C ++

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

19
Ladybro

Vous devez l'appeler de cette façon:

Alg::dijkstra();

Limitations

  • Impossible d'appeler d'autres fonctions de classe qui ne sont pas statiques.
  • Impossible d'accéder aux membres de données de classe non statiques.
  • Peut instancier un objet via new class() lorsque le constructeur est privé/protégé. Par exemple. une fonction d'usine.
25
egur

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

Ê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();
}
6
Alex

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.

1
VladimirM

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:

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

0
blackbird

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".

0
KeithSmith

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.

0
blackbird

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.

0
Prashant Kumar