0

I'm working on a homework assignment for school. For the main loop I circle trough the Objects and call their Update function, each Object has two Object pointers witch are used to make a linked-list. I made these pointers private, and made two friend functions GetNext witch provides the Next pointer, and SetPointers witch sets the pointers. these functions are in the ObjectManager class and they are private. I can't seem to get the Object class to get access to their definition without causing other errors.

the Object Class:

   namespace Tmpl8{
   class Colider;

   class ObjectManager;
   class PhysicsManager;

   class Object{
   public:
        Object();
        ~Object();

        virtual void Update();

   private:
        Object* Next;
        Object* Previus;

        friend Object* ObjectManager::GetNext(Object* object);
        friend void ObjectManager::SetPointers(Object* object, Object* next, Object* previus);
   };

the ObjectManager Class:

    namespace Tmpl8{
    class Object;
    class GameObject;
    class Colider;

    class ObjectManager{
    public:
        ObjectManager();
        ~ObjectManager();

        void Update();
        void Remove(Object* object);
        void Add(Object* object);

    private:
        void Resolve();
        std::vector<Object*> removeList;
        std::vector<Object*> addList;

        Object* first;
        Object* last;

        Object* GetNext(Object* object);
        void SetPointers(Object* object, Object* next, Object* previus);
   };

the GetNext function

    Object* ObjectManager::GetNext(Object* object)
    {
        return object->Next; // this gives the error Tmpl8::Object::Next(delecared at...) is inaccessible   
    }

the build log:

    1>c:\all svn\student.141960.school_projects\programing\block 2\micro    machines_02\object.h(25): error C2248: 'Tmpl8::ObjectManager::GetNext' : cannot access private member declared in class 'Tmpl8::ObjectManager'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\manager.h(29) : see declaration of 'Tmpl8::ObjectManager::GetNext'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\manager.h(12) : see declaration of 'Tmpl8::ObjectManager'
    1>c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\object.h(26): error C2248: 'Tmpl8::ObjectManager::SetPointers' : cannot access private member declared in class 'Tmpl8::ObjectManager'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\manager.h(30) : see declaration of 'Tmpl8::ObjectManager::SetPointers'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\manager.h(12) : see declaration of 'Tmpl8::ObjectManager'
    1>  manager.cpp
    1>c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\object.h(25): error C2027: use of undefined type 'Tmpl8::ObjectManager'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\object.h(11) : see declaration of 'Tmpl8::ObjectManager'
    1>c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\object.h(26): error C2027: use of undefined type 'Tmpl8::ObjectManager'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\object.h(11) : see declaration of 'Tmpl8::ObjectManager'
    1>manager.cpp(40): warning C4018: '<' : signed/unsigned mismatch
    1>manager.cpp(45): warning C4018: '<' : signed/unsigned mismatch
    1>manager.cpp(57): error C2248: 'Tmpl8::Object::Next' : cannot access private member declared in class 'Tmpl8::Object'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\object.h(22) : see declaration of 'Tmpl8::Object::Next'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\object.h(14) : see declaration of 'Tmpl8::Object'
    1>  object.cpp
    1>c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\object.h(25): error C2248: 'Tmpl8::ObjectManager::GetNext' : cannot access private member declared in class 'Tmpl8::ObjectManager'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\manager.h(29) : see declaration of 'Tmpl8::ObjectManager::GetNext'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\manager.h(12) : see declaration of 'Tmpl8::ObjectManager'
    1>c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\object.h(26): error C2248: 'Tmpl8::ObjectManager::SetPointers' : cannot access private member declared in class 'Tmpl8::ObjectManager'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\manager.h(30) : see declaration of 'Tmpl8::ObjectManager::SetPointers'
    1>          c:\all svn\student.141960.school_projects\programing\block 2\micro machines_02\manager.h(12) : see declaration of 'Tmpl8::ObjectManager'
    1>  Generating Code...

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

  • 1
    That `friend` declaration isn't even valid (because `ObjectManager` isn't known yet); presumably you've only pasted the last error to us and ignored all the rest? – Lightness Races in Orbit Dec 23 '14 at 11:35
  • I can't why isn't it valid? – theRealFlobo Dec 23 '14 at 11:36
  • 1
    You're trying to make a member function of `ObjectManager` a friend before the compiler knows that `ObjectManager` has such a member function. That's illegal. One of your compiler errors is telling you that (unless MSVS has some horrific extension in this regard that I'm not aware of) – Lightness Races in Orbit Dec 23 '14 at 11:40
  • 2
    You could just do `friend class ObjectManager;` and call it a day. – Barry Dec 23 '14 at 11:44
  • any way to fix that except making the class a friend like @Barry suggested – theRealFlobo Dec 23 '14 at 11:47
  • @theRealFlobo: You'd need to define (not just declare) `ObjectManager` before `Object`; and also make `Object` a friend of `ObjectManager` so it can name private members in its friend declarations. Making `ObjectManager` a friend of `Object` would be much cleaner. – Mike Seymour Dec 23 '14 at 11:56

1 Answers1

0

There are two solutions that I know of (assuming you can't put the entire declaration of ObjectManager ahead of Object). The simple one is:

friend class ObjectManager; 

You're already friending two methods, why not friend all of them? The more complicated one involves the use of a passkey and, in this case, is clearly worse:

template <typename T>
class PassKey;

class ObjectManager;

class Object {
public:
    Object* GetNext(PassKey<ObjectManager> ) { return Next; }
    void SetPointers(PassKey<ObjectManager>, Object*, Object* ) { .. }
};

with:

template <typename T>
class PassKey {
    friend T;
    PassKey() { }
};

Here, GetNext() and SetPointers() are public functions on Object, but they require a PassKey which is privately constructed and whose only friend is ObjectManager. Thus, the ObjectManager can do:

Object* ObjectManager::GetNext(Object* object)
{
    return object->GetNext(PassKey<ObjectManager>());
}

However, this really muddles the interface to what in my opinion is no benefit as compared to just friending the whole class.

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977