2012-04-27 9 views
29

Tengo dos clases, Mesh y MeshList. Quiero que MeshList tenga una función que pueda cambiar los miembros privados de Mesh. Pero no compilará y no sé por qué. Aquí está mi código.C++ no me deja hacer amigos

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

me sale estos errores:

MeshList.h (línea 11)

  • error C2143: error de sintaxis: falta ';' antes de '*'
  • error C4430: especificador de tipo faltante - int assume. Nota: C++ no apoyo error
  • default-int C4430: falta el especificador de tipo - int asumido. Nota: C++ no apoyo default-int

  • mesh.h (11): error C2653: 'MeshList': no ​​es una clase o espacio de nombres nombre

  • meshlist.cpp (5): error C2248 : 'Mesh :: vboHandle_': no ​​se puede acceder miembro privado declarado en la clase 'malla'
  • mesh.h (10): véase la declaración de 'Mesh :: vboHandle_'
  • mesh.h (8): véase la declaración de 'Mesh'
  • meshlist.cpp (5): error C2100: direccionamiento indirecto
+38

Tienes que salir más. –

+32

+1 solo por el título. –

+5

Pruebe 'class Meshlist;' en lugar de '#include" MeshList.h "' – chris

Respuesta

6

dependencias cíclicas se explican en las otras respuestas ...

Aquí viene la solución:

En MeshList.h:

  • reemplazar #include "Mesh.h" con la declaración hacia adelante class Mesh; (Usted don 't need the include here, porque solo declaras un puntero a Mesh)

En MeshList.cpp:

  • añadir #include "Mesh.h" a tu incluye (se necesita la declaración, ya que se utiliza la malla)

El último error de compilación, usted ha mencionado es otro problema:

*mesh->vboHandle_ = 4; 

mesh es un puntero. Su código selecciona el miembro vboHandle_ e intenta desreferenciarlo (que falla). Supongo que te refieres a:

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

Se corrigió la respuesta de acuerdo con el comentario de David. – Stephan

9

Al compilar Mesh.cpp, que incluye Mesh.h, que incluye MeshList.h, que comienza a incluir Mesh.h pero se detiene antes de tiempo porque _MESH_H se define ahora. Luego (de vuelta en MeshList.h) hay una referencia al Mesh, pero eso aún no se ha declarado. Por lo tanto, p. Ej., Su error C2143.

+0

@ildjarn, eso es interesante ya que nunca lo descubrí en ninguna parte. ¿Puedo preguntar por qué? – chris

+0

@chris: ¡Tendría que preguntarle a las personas que diseñaron C++! – ildjarn

+0

@ildjarn: ¿Estás seguro?De hecho, estoy bastante seguro de que todo lo contrario es cierto. Incluso pienso recordar que el estándar establecía que hacer amistad con una clase era equivalente a hacerse amigo de todas sus funciones ... Tendré que buscar la cita, supongo. –

6

Es porque usted ha #include "MeshList.h" en el archivo Mesh.h, por lo que el archivo MeshList.h se compilará en primer lugar, y la clase Mesh aún no se declara. Para eso el compilador pensará que Mesh en la línea de error es un nombre de variable que no tiene un tipo anterior, de ahí el error.

Este es un ejemplo de lo que una función miembro de 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; 
} 
4

el problema: dependencias cíclicas en su incluye. El mensaje de error es menos que ideal, desafortunadamente.


La solución: Si te haces amigo de toda la clase, en lugar de una sola función, a continuación, se puede utilizar una declaración adelantada de la clase para romper el ciclo.

// 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 

Algunos (subjetivas) directrices:

  • Incluir también las cosas en orden inverso al de su capacidad de cambiar si se rompe, es decir: STL primera, cabeceras de 3 ª parte segunda, su propia pila de middleware tercera, el proyecto actual incluye la cuarta y la biblioteca actual incluye la quinta. De esta forma, si hay un conflicto, con suerte el error apuntará a un encabezado tuyo.

  • Ponga las cosas public antes de las cosas private en una clase. Los clientes de la clase solo se preocupan por la interfaz pública, no es necesario que revisen todos los detalles sucios de la implementación para poder acceder a ella.

+0

Según tengo entendido, no necesita una declaración directa si su declaración de amigo está por encima del primer uso. (He probado un ejemplo similar sin clase MeshList; en VS y funciona.) – anxieux

+0

@anxieux: Nunca entendí completamente en qué ámbito se inyectó el nombre después de 'friend class' si no se pudo encontrar; así que tomé el hábito de simplemente anunciar el tipo. Un poco más detallado, tal vez, pero bueno: ¡funciona el 100% del tiempo! –

Cuestiones relacionadas