Alex Rivera | Logout

C++ won't let me make friends

Asked 2012-04-27T01:17:12.443
32

I have two classes, Mesh and MeshList. I want MeshList to have a function that can change the private members of Mesh. But it won't compile and I don't know why. Here's my code.

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

I get these errors:

MeshList.h (Line 11)

  • error C2143: syntax error : missing ';' before '*'
  • error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
  • error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

  • mesh.h(11) : error C2653: 'MeshList' : is not a class or namespace name

  • meshlist.cpp(5) : error C2248: 'Mesh::vboHandle_' : cannot access private member declared in class 'Mesh'
  • mesh.h(10) : see declaration of 'Mesh::vboHandle_'
  • mesh.h(8) : see declaration of 'Mesh'
  • meshlist.cpp(5) : error C2100: illegal indirection
Edit
Report

2 Answers

6

It's because you've #include "MeshList.h" in the file Mesh.h, so the file MeshList.h will be compiled first, and the class Mesh is not yet declared. For that the compiler will think that Mesh in the error line is a variable name that has not got a type before it, hence the error.

This is an example of making a friend member function:

#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;
}
answered 2012-04-27T01:24:31.777
4

The problem: Cyclic dependencies in your includes. The error message is less than ideal, unfortunately.


The solution: If you befriend the whole class, instead of a single function, then you can use a forward declaration of the class to break the 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

Some (subjective) guidelines:

  • Include stuff in reverse order of your ability to change it if it breaks, that is: STL first, 3rd party headers second, your own middleware stack third, the current project includes fourth and the current library includes fifth. This way, if there is a conflict, hopefully the error will point to a header of yours.

  • Put the public stuff before the private stuff in a class. Clients of the class are only concerned with the public interface, no need to have them wade through all the dirty implementation details before they can get to it.

answered 2012-04-27T06:38:36.443

Your Answer