30 votes

C ++ ne me laisse pas me faire des amis

J'ai deux classes, Mesh et MeshList. Je veux MeshList d'avoir une fonction qui permet de changer les membres privés de la Maille. Mais il ne compile pas et je ne sais pas pourquoi. Voici mon code.

Maillage.h

#ifndef _MESH_H
#define _MESH_H

#include "MeshList.h"
#include <iostream>

class Mesh
{
private:
    unsigned int vboHandle_;
    friend void MeshList::UpdateVBOHandle();
public:
    inline void Out() {std::cout << vboHandle_;}
};
#endif

Mesh.cpp

#include "Mesh.h"

MeshList.h

#ifndef _MESH_LIST_H
#define _MESH_LIST_H

#include "Mesh.h"


class MeshList
{

public:
    Mesh *mesh; //Line 11 Error
    void UpdateVBOHandle();
};
#endif

MeshList.cpp

#include "MeshList.h"

void MeshList::UpdateVBOHandle()
{
    *mesh->vboHandle_ = 4;
}

J'obtiens ces erreurs:

MeshList.h (Ligne 11)

  • error C2143: erreur de syntaxe : manquant ';' avant '*'
  • error C4430: spécificateur de type manquant - int assumé. Remarque: C++ ne prend pas en par défaut-int
  • error C4430: spécificateur de type manquant - int assumé. Remarque: C++ ne prend pas en par défaut-int

  • maillage.h(11) : erreur C2653: 'MeshList": n'est pas une classe ou d'un espace de noms nom

  • meshlist.cpp(5) : erreur C2248: 'Mesh::vboHandle_' : ne peut pas accéder membre privé déclarée dans la classe 'Mesh'
  • maillage.h(10) : voir la déclaration de 'Mesh::vboHandle_'
  • maillage.h(8) : voir la déclaration de 'Mesh'
  • meshlist.cpp(5) : erreur C2100: illégal d'indirection

9voto

Gareth McCaughan Points 12261

Lorsque vous compilez Mesh.cpp , cela inclut Mesh.h , qui comprend MeshList.h , qui commence à inclure Mesh.h mais s'arrête tôt car _MESH_H est maintenant défini. Ensuite (en arrière en MeshList.h ) il y a une référence à Mesh - mais cela n'a pas encore été déclaré. Par conséquent, par exemple, votre erreur C2143.

6voto

Tamer Shlash Points 3939

C'est parce que vous avez #include "MeshList.h" dans le fichier Mesh.h , donc le fichier MeshList.h sera compilé en premier, et la classe Mesh n'est pas encore déclaré. Pour cela, le compilateur pensera que Mesh dans la ligne d'erreur est un nom de variable qui n'a pas de type avant, d'où l'erreur.

Voici un exemple de création d'une fonction membre friend :

 #include <iostream>


class foo;

class bar
{
public:
    void barfunc(foo &f);
};

class foo
{
private:
    friend void bar::barfunc(foo &f);
    int i;
public:
    foo()
    {
        i = 0;
    }
    void printi()
    {
        std::cout << i << '\n';
    }
};

void bar::barfunc(foo &f)
{
    f.i = 5;
}


int main()
{
    foo f;
    bar b;
    b.barfunc(f);
    f.printi();
    return 0;
}
 

6voto

Stephan Points 2496

Cyclique dépendances sont expliqués dans les autres réponses...

Voici la solution:

En MeshList.h:

  • remplacer #include "Mesh.h" avec la déclaration anticipée class Mesh; (Vous n'avez pas besoin de l'inclure ici, parce que vous ne déclarez un pointeur vers un Maillage)

En MeshList.cpp:

  • ajouter #include "Mesh.h" de votre comprend (vous avez besoin de la déclaration, parce que vous utilisez le Maillage)

La dernière erreur de compilation, vous avez mentionné est un autre problème:

*mesh->vboHandle_ = 4;

mesh est un pointeur. Votre code sélectionne le membre vboHandle_ et tente de déréférencement (qui échoue). Je suppose que tu veux dire:

mesh->vboHandle_ = 4; // <-- no leading asterisk

4voto

Matthieu M. Points 101624

Le problème: Cyclique des dépendances dans votre comprend. Le message d'erreur n'est pas idéale, malheureusement.


La solution: Si vous lier d'amitié avec l'ensemble de la classe, au lieu d'une seule fonction, vous pouvez utiliser une déclaration anticipée de la classe afin de briser le cycle.

// Mesh.h
#ifndef _MESH_H
#define _MESH_H

#include <iostream>

class MeshList;

class Mesh
{
private:
    unsigned int vboHandle_;
    friend class MeshList;
public:
    inline void Out() {std::cout << vboHandle_;}
};
#endif

Certains (subjective) des lignes directrices:

  • Inclure des choses dans l'ordre inverse de votre capacité à changer, si ça casse, c'est: STL première, 3e partie les en-têtes de seconde, votre propre pile de middleware troisième, le projet actuel comprend quatrième et la bibliothèque actuelle comprend cinquième. De cette façon, si il y a un conflit, espérons-le, l'erreur sera point à un en-tête de la vôtre.

  • Mettre la public trucs avant de l' private trucs dans une classe. Les Clients de la classe ne sont concernés par l'interface publique, pas besoin de les avoir à patauger dans tous les sales détails de mise en œuvre avant qu'ils puissent obtenir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X