Friend class in C++ not allowing access to private member attributes - c++

I recently started C++ and to be completely honest my lecturer isn't much help, I am trying to give a linked list friend access to a node class. From what I can see I have declared everything I need, but I still cant access the Node private members , if somebody could see something im missing that would be great!
My node header file:
```#ifndef NodeofBook_h
#define NodeofBook_h
#include <stdio.h>
#include "Book.h"
class ListOfBooks;
//
class NodeofBook {
friend class ListOfBooks;
private:
NodeofBook* next;
Book* theBook;
public:
};
#endif /* NodeofBook_h */
My linked list header file :
#ifndef ListOfBooks_h
#define ListOfBooks_h
#include <stdio.h>
#include "NodeofBook.h"
class ListOfBooks {
private:
public:
ListOfBooks();
void insertBack(int);
void displayList();
int deleteMostRecent();
int deleteInt(int pos);
};
#endif /* ListOfBooks_h */
My Linked List cpp file:
#include "ListOfBooks.h"
int ListOfBooks(){
return 0;
}
ListOfBooks::ListOfBooks(){
theBook->title = "noTitleYet";
theBook->isbn = 0000;
next = NULL;
}
I am getting an error stating Use of undeclared identifier 'theBook'
Any help is really appreciated!

NodeofBook declaring that ListofBooks is a friend class just means that the implementation of ListofBooks can access NodeofBook's private members, but there still needs to be an instance of NodeofBook to access. Its members are not static; non-static member variables are part of some object. That is, just because the ListofBooks is a friend of NodeofBook does not mean that it magically has instances of NodeofBookmembers.
A friend relationship is not an is-a relationship like inheritance: it is just about access.

Related

Troubles with Circular Dependencies between 3 classes and with inheritance

I'm a first-year college student that doesn't know everything about CS yet, so please bear with my newness to it, and this is my first question on here.
For an assignment, we are making faux version of Pokemon Go to practice using polymorphism in c++, and I'm running into some compiler errors. Here are the three files with just a sample of the code in them:
#ifndef EVENT_H
#define EVENT_H
#include <string>
#include "Trainer.h"
class Event{
protected:
std::string title;
public:
Event();
~Event();
virtual void action(Trainer) = 0;
};
#endif
Trainer.h:
#ifndef TRAINER_H
#define TRAINER_H
#include "Pokemon.h"
class Trainer{
private:
Pokemon* pokemon;
int num_pokemon;
public:
Trainer();
~Trainer();
//include accessors and mutators for private variables
};
#endif
Pokemon.h:
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event{
protected:
std::string type;
std::string name;
public:
Pokemon();
~Pokemon();
virtual bool catch_pokemon() = 0;
};
#endif
The trainer.h file is a parent class for each pokemon type (eg Rock) which just defines a few virtual functions. The error I'm getting is when I'm compiling all of this and I get something that says:
Pokemon.h : 5:30: error: expected class-name befoer '{' token:
class Pokemon : Event {
Pokemon need to be a derived class to an event, so that an event pointer can point in another Location class can point to either a pokemon, pokestop, or cave for the assignment, and I have been looking online for hours and can't figure out what to do. I would appreciate the help! Let me know if you need more info or something because again, this is my first time posting a question.
You need some forward declarations.
In Event.h, you can put class Trainer; instead of #include "Trainer.h". In Trainer.h, you can put class Pokemon; instead of #include "Pokemon.h".
You will probably need to include the appropriate headers in the corresponding source files in order to actually use the other classes. But by avoiding the includes in the header files, you get out of the circular dependency trouble.
Pokemon.h must continue to #include "Event.h", since you're inheriting Event, which requires a complete definition.
Use forward declaration, to tell classes the type they need to use will be defined later. You can use forward declaration in situations where the size is know, pointers and references are always the same size regardless of the type they point to so use them.
#ifndef EVENT_H
#define EVENT_H
#include <string>
class Trainer;
class Event
{
protected:
std::string title;
public:
Event();
virtual ~Event();
virtual void action(Trainer* const trainer) = 0;
};
#endif
then
#ifndef TRAINER_H
#define TRAINER_H
class Pokemon;
class Trainer
{
private:
Pokemon* const pokemon;
int numPokemon;
public:
Trainer();
~Trainer();
};
#endif
then
#ifndef POKEMON_H
#define POKEMON_H
#include "Event.h"
#include <string>
class Pokemon : public Event
{
protected:
std::string type;
std::string name;
public:
Pokemon();
virtual ~Pokemon();
virtual bool catchPokemon() = 0;
};
#endif
when using polymorphism (virtual functions) you must always make the base class destructor virtual too. It is also nice to make the derived classes destructor virtual as well, but it is not required.

My class (container of pointers to another class) cannot seem to access the public constructor

I am struggling to create a QList of pointers to objects of a self-made class, in this case Node. I have tried to use the same method as in the Library example of An Introduction to Design Patterns in C++ with Qt, Ezust and Ezust.
For some reason, the container class NodeList cannot access the constructor in the Node class and complains that it is private, even though it is public.
I have tried using the friend keyword in the definition of Node, but that did not work either. I cannot see where the problem is coming from, as I am referencing the pointers in exactly the same way as the working example from the textbook.
#ifndef NODE_H
#define NODE_H
#include <QString>
#include <QList>
class Node
{
public:
Node() {}
void setNodeLabel(QString label);
QString getNodeLabel();
Node(QString label);
private:
QString nodeLabel;
};
class NodeList : public QList<Node*>
{
public:
NodeList() {}
~NodeList();
void addNode(Node*& node);
private:
NodeList(const NodeList&);
NodeList& operator=(const NodeList&);
};
#endif // NODE_H
The error I get when trying to compile this is as follows:
\qlist.h:106: error: 'struct QList<Node*>::Node' is private
struct Node { void *v;
^
\node.h:25: error: within this context
void addNode(Node*& node);
^
NodeList derives from QList<Node*>, which has a nested class named Node, which is in the private section of QList. When you use the unqualified type Node anywhere in NodeList, that name resolves to QList<Node*>::Node. Hence, you get that error.
Unless you intend to add more functionality to NodeList, you can use:
using NodeList = QList<Node*>;
and get rid of the class NodeList.

Friend function can't access private members

I'm trying to get a friend function of class1 and ships to access the private members of both, but it says that those members are inaccessible.
The code is below, the problem is in ships.cpp. I tried to reproduce this problem in an even more simple manner in a single file but it didn't happen there, so I don't know what's wrong here. Maybe it's a circular declaration problem?
ships.h
#ifndef _SHIPS_H_
#define _SHIPS_H_
#include "point.h"
class class1;
class Ships{
public:
friend char* checkpoints();
private:
Point ship[6];
};
#endif // ! _SHIPS_H_
ships.cpp
#include "ships.h"
#include "class1.h"
char* checkpoints(Ships ship, class1 game) {
ship.ship[0];//cannot access private member declared in class 'Ships'
game.smallship;//cannot access private member declared in class 'class1'
return nullptr;
}
class1.h
#ifndef _CLASS1_H_
#define _CLASS1_H_
#include "ships.h"
class class1 {
public:
friend char* checkpoints();
private:
static const int LIVES = 3;
Ships smallship, bigship;
};
#endif
Just making my comment an answer. You declared char* checkpoints() as a friend function. Declare the correct prototype char* checkpoints(Ships ship, class1 game) as a friend instead.
You also probably want to use references (maybe const) otherwise the arguments are passed by value (copy): char* checkpoints(Ships& ship, class1& game)

C++: Two classes referencing each other

So to toy with friend functions, I decided to make a Child class and a Mother class. The Mother class has a data member that is a Child. The Child class makes two methods of the Mother class friend functions.
When I compile though, it seems that no matter how I handle inclusions I end up with an error. If the Child is the first one to get defined, I get "Mother is not a class or namespace name" for the line friend void Mother::setChildName(string name); in Child.h. If the Mother is the first one to get defined, I get "Missing type specifier" for the line Child c; in Mother.h.
Is there a way around this? I tried putting class Mother; at the top of the Child.h and class Child; at the top of Mother.h and that didn't seem to help.
Or is this kind of circular reference just always going to fail?
In Mother.h:
#ifndef MOTHER_H_
#define MOTHER_H_
#include <string>
#include "Child.h"
using namespace std;
class Mother {
public:
Mother();
void setChildName(string name);
string getChildName();
private:
Child c;
};
#endif
In Mother.cpp:
#include <string>
#include "Mother.h"
using namespace std;
void Mother::setChildName(string name) {
c.name = name;
}
string Mother::getChildName() {
return c.name;
}
In Child.h:
#ifndef CHILD_H_
#define CHILD_H_
#include <string>
#include "Mother.h"
using namespace std;
class Child {
public:
private:
string name;
friend void Mother::setChildName(string name);
friend string Mother::getChildName();
};
#endif
This particular problem cannot be solved without redesign. Mother needs to be defined before Child, and Child needs to be defined before Mother. The simple way is to make the whole Mother class a friend of Child. That way Child can be defined first.
I think there little practical benefit in making individual methods friends of another class. That would imply that your class is so big that it's responsibilities could be divided into smaller classes.
if Mother will hold pointer to child, you will not have to include child.h. forward deceleration will be enough.

How can a class A, that is a member of class B, share private members of class B?

I have the following code:
Master.h
#ifndef MASTER_H
#define MASTER_H
class Master
{
friend class Friend;
public:
Master(void);
~Master(void);
void CallFriendFunction(int largeData);
private:
int largeData;
//Want this class to share largeData;
Friend testFriend;
};
#endif // MASTER_H
Master.cpp
#include "Master.h"
Master::Master(void)
{
//Inentionally left blank
}
Master::~Master(void)
{
//Intentionally left blank
}
void Master::CallFriendFunction(int largeData)
{
this->largeData = largeData;
this->testFriend.Test(this);
}
Friend.h
#ifndef FRIEND_H
#define FRIEND_H
#include "Master.h"
class Friend
{
public:
Friend(void);
~Friend(void);
void Test(Master* masterPtr);
};
#endif // FRIEND_H
Friend.cpp
#include "Friend.h"
#include <iostream>
Friend::Friend(void)
{
//Intentionally left blank
}
Friend::~Friend(void)
{
//Intentionally left blank
}
void Friend::Test(Master* masterPtr)
{
std::cout << masterPtr->largeData << std::endl;
}
I want class Friend to be able to share Master's private members. However, I can't get this code to compile. I've tried Forward Declaration, and #includes, but I start getting into circular dependencies. When Friend class is not a member of Master class, the code compiles?
Is it possible for Friend class be a member of Master and be friends?
How else can Friend class have access to Masters private members?
You need the following includes and forward declarations:
In Master.h:
#include "Friend.h"
In Friend.h:
class Master;
In Friend.cpp:
#include "Master.h"
Putting the forward declaration in Friend.h prevents circular dependency. A forward declaration is enough there because you only declare a Master* parameter, without using its members yet.
You do need to include Friend.h from Master.h because you are declaring a Friend member, and this requires a complete type.
It looks like you're struggling with circular dependencies. Note that, to make something a friend you do not need to include it. That said, in your Master class, you instantiate friend which requires its inclusion as a header (otherwise the compiler will be all WTF?).
However, in friend.h you can simply forward-declare the master class and not directly include it:
class Master;
This is because you are not attempting to instantiate the Master class, but use a pointer to it.