How to make a sub class a friend in another class?

J

Jim Langston

Short version:
class MyClass
{
friend class MyOtherClass::MySubClass; // Doesn't work
};

class MyOtherClass
{
class MySubClass
{
// Need to access private members of MyClass here
} MySubInstance;
};

Here is something more close to what I am trying to do showing the problem:

#include <iostream>
#include <string>

class COffsetMap
{
public:
void SetBase( void* Base ) { }
void SetOffset( int& Var ) { }
};

class CHealth
{
public:
friend class CCharacter::CCharFieldMap; // Doesn't work
private:
int Mana_;
int ManaMax_;
};

class CCharacter
{
public:
class CCharFieldMap: public COffsetMap
{
public:
void SetMap( CCharacter* Base )
{
SetBase( Base );
SetOffset( Base->Version );
SetOffset( Base->Health.Mana_ ); // Can't access private
SetOffset( Base->Health.ManaMax_ ); // Can't access private
}
} CharFieldMap;

private:
int Version;
CHealth Health;

};

int main()
{
CCharacter Char;

std::cout << "Press Return";
std::string wait;
std::getline( std::cin, wait );
return 0;
}


I've tried various ways around this to no avail. Is this possible?
 
I

Ian Collins

Jim said:
Short version:
class MyClass
{
friend class MyOtherClass::MySubClass; // Doesn't work
};

class MyOtherClass
{
class MySubClass
{
// Need to access private members of MyClass here
} MySubInstance;
};
Do it the other way round:

class MyOtherClass
{
friend class MyClass;

class MySubClass
{
// Need to access private members of MyClass here
} MySubInstance;
};

class MyClass
{
friend class MyOtherClass::MySubClass; // Does work
};
 
J

Jim Langston

Ian Collins said:
Do it the other way round:

class MyOtherClass
{
friend class MyClass;

class MySubClass
{
// Need to access private members of MyClass here
} MySubInstance;
};

class MyClass
{
friend class MyOtherClass::MySubClass; // Does work
};

That doesn't work, because (as I forgot to show in my short version)
MyOtherClass has a private instance of MyClass in it.

If I declare MyClass after MyOtherClass than I get the error
error C2079: 'CCharacter::Health' uses undefined class 'CHealth'
even if I do
class MyClass;

Even if I make the instance a pointer declartion with
MyClass* MyInstance;
then MySubClass gets errors when it attempts to access the variables:
error C2027: use of undefined type 'CHealth'
see declaration of 'CHealth'

I even tried taking the class definition of MySubClass out of MyOtherClass
but then I get the problem that MySubClass needs to see the definition of
MyClass to access the variables, but as you seem to indicate, MyClass also
needs to see the definition of MyOtherClass first.

ug.

Can you get this to compile by any manipulations?

#include <iostream>
#include <string>

class COffsetMap
{
public:
void SetBase( void* Base ) { }
void SetOffset( int& Var ) { }
};

class CCharacter
{
public:
class CCharFieldMap: public COffsetMap
{
public:
void SetMap( CCharacter* Base )
{
SetBase( Base );
SetOffset( Base->Version );
SetOffset( Base->Health->Mana_ );
SetOffset( Base->Health->ManaMax_ );
}
} CharFieldMap;

private:
int Version;
CHealth* Health;

};

class CHealth
{
public:
friend class CCharacter::CCharFieldMap; // Doesn't work
private:
int Mana_;
int ManaMax_;
};

int main()
{
CCharacter Char;
Char.SetMap( &Char );

std::cout << "Press Return";
std::string wait;
std::getline( std::cin, wait );
return 0;
}
 
I

Ian Collins

Jim said:
That doesn't work, because (as I forgot to show in my short version)
MyOtherClass has a private instance of MyClass in it.

If I declare MyClass after MyOtherClass than I get the error
error C2079: 'CCharacter::Health' uses undefined class 'CHealth'
even if I do
class MyClass;

Even if I make the instance a pointer declartion with
MyClass* MyInstance;
then MySubClass gets errors when it attempts to access the variables:
error C2027: use of undefined type 'CHealth'
see declaration of 'CHealth'

I even tried taking the class definition of MySubClass out of MyOtherClass
but then I get the problem that MySubClass needs to see the definition of
MyClass to access the variables, but as you seem to indicate, MyClass also
needs to see the definition of MyOtherClass first.

ug.

Can you get this to compile by any manipulations?

#include <iostream>
#include <string>

class COffsetMap
{
public:
void SetBase( void* Base ) { }
void SetOffset( int& Var ) { }
};

class CCharacter
{
public:
class CCharFieldMap: public COffsetMap
{
public:
void SetMap( CCharacter* Base )
{
SetBase( Base );
SetOffset( Base->Version );
SetOffset( Base->Health->Mana_ );
SetOffset( Base->Health->ManaMax_ );
}
} CharFieldMap;

private:
int Version;
CHealth* Health;

};
Why not untangle the dependencies and extract CCharFieldMap from its
containing class?
 
J

Jim Langston

Ian Collins said:
Why not untangle the dependencies and extract CCharFieldMap from its
containing class?

Tried that too. Couldn't get it to work either.

I even took the declaration/definition of CCharFieldMap out of CCharacter,
then in CCharacter I only do
CCharFieldMap CharFieldMap;
but that still wouldn't compile.

CCharFieldMap needs to be in CCharacter for usage. Otherwise it will
complicate usage quite a bit.
 
I

Ian Collins

Jim said:
Tried that too. Couldn't get it to work either.

I even took the declaration/definition of CCharFieldMap out of CCharacter,
then in CCharacter I only do
CCharFieldMap CharFieldMap;
but that still wouldn't compile.

CCharFieldMap needs to be in CCharacter for usage. Otherwise it will
complicate usage quite a bit.
It can still be a member, even if it isn't a nested class.

If you can't get it to compile in one file, give each class its own
header and source file and use appropriate forward declarations in the
headers. If that doesn't work, your design is too tangled and will have
to change.
 
J

Jim Langston

Ian Collins said:
It can still be a member, even if it isn't a nested class.

If you can't get it to compile in one file, give each class its own
header and source file and use appropriate forward declarations in the
headers. If that doesn't work, your design is too tangled and will have
to change.

Well, I finally got it to compile. It's just very tricky in that things
have to be done in an exact order. Makes it a little difficult for the
user.

#include <iostream>
#include <string>

class COffsetMap
{
public:
void SetBase( void* Base ) { }
void SetOffset( int& Var ) { }
};

class CHealth
{
public:
friend class CCharFieldMap;
private:
int Mana_;
int ManaMax_;
};

class CCharacter;

class CCharFieldMap: public COffsetMap
{
public:
void SetMap( CCharacter* Base );
};

class CCharacter
{
public:
friend class CCharFieldMap;
CCharFieldMap CharFieldMap;

private:
int Version;
CHealth Health;

};

void CCharFieldMap::SetMap( CCharacter* Base )
{
SetBase( Base );
SetOffset( Base->Version );
SetOffset( Base->Health.Mana_ );
SetOffset( Base->Health.ManaMax_ );
}

int main()
{
CCharacter Char;
Char.CharFieldMap.SetMap( &Char );

std::cout << "Press Return";
std::string wait;
std::getline( std::cin, wait );
return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top