Reputation: 69
I am doing my project which is simulation of school system.
I have problem with the fact that a method from class Klasa (Polish for class) cannot access private data from class Student, even though I declared this method as a friend in Student.
Here is the code:
First Student.h:
#include <iostream>
#include "Klasa.h"
#include "SubjectType.h"
#include "SubjectGrades.h"
using namespace std;
class Klasa;
class SubjectGrades;
class Student
{
private:
char* name;
int id;
Klasa* myClass;
//School* mySchool;
int classIndex; //numer w dzienniku - zrobić prywatne z akcesorami
static int counter;
public:
Student();
Student(char*);
Student(const Student&);
Student& operator= (const Student&);
~Student();
//bool assignToSchool(School*)
//bool resignFromSchool();
void assignToClass(Klasa*);
void resignFromClass();
double getMyAverageGrade(SubjectType type) const ; //srednia ocen z danego przedmiotu dla danego ucznia
double getMyAverageGrade() const; //średnia ocen dla danego ucznia
bool operator== (const Student&);
bool operator!= (const Student&);
friend ostream& operator<< (ostream&, const Student&);
// akcesory
int GetclassIndex() const;
int SetclassIndex(int i);
friend bool Klasa::assignToKlasa(Student* s);
char* GetName() const { return name; }
};
Now method from class Klasa:
bool Klasa::assignToKlasa(Student* s)
{
if(studentCount < maxStudentCount)
{
if(containsStudent(s))
return false;
if(studentCount < klasaSize) //jest miejsce dla studenta
{
int i = 0;
while(studentList[i] != NULL)
i++;
studentList[i] = s;
s->classIndex=i;// = i; //tu musi byc setter
}
//WHATS BELOW DOESN'T MATTER FOR THIS PROBLEM, SO U DON;T NEED TO READ.
else
{
cout << "Zwiekszamy rozmiar!\n";
//musimy zwiększyć rozmiar tablicy studentList
Student** newStudentList = new Student*[klasaSize + sizeStep];
for(int i = 0; i < klasaSize; ++i)
newStudentList[i] = studentList[i];
for(int i = klasaSize; i < klasaSize + sizeStep; ++i)
newStudentList[i] = NULL;
klasaSize += sizeStep;
delete[] studentList;
studentList = newStudentList;
studentList[studentCount] = s;
s->SetclassIndex(studentCount); //tu ma byc setter
}
s->assignToClass(this); //mówimy studentowi - "jestem twoją klasą"
studentCount++;
cout << "Dodano studenta!\n";
return true;
}
return false;
}
It underlines s->classIndex=i
that classIndex cannot be accessed.
Also in Klasa.h I declared this method like: bool assignToKlasa(Student* s);
So I have no idea why it doesn't let me access private data from student after I declared it in student as a friend? Could you please help me?
Upvotes: 2
Views: 4473
Reputation: 45424
For this equivalent code
class A;
class B {
int x;
public:
B(int __x) : x(__x) {}
friend bool A::method(B*) const; // error: undefined member cannot be friend
//friend class A; // fine: class A is declared and can be used
};
class A {
int y;
pu8blic:
A(int __y) : y(__y) {}
bool method(B*b) const
{ return y == b->x; }
};
I get the error messages (with gcc 4.3.2):
test3.cc:7: error: invalid use of incomplete type ‘struct A’
test3.cc:1: error: forward declaration of ‘struct A’
test3.cc: In member function ‘bool A::method(B*) const’:
test3.cc:3: error: ‘int B::x’ is private
test3.cc:15: error: within this context
The first error is the only one you have to worry about (the others are either explanations or consequences of the first). So how can one sort this out? One simple way to fix the problem is to declare the whole class A
to be friend of B
by replacing
friend bool A::method(B*) const;
with
friend class A;
which is defined.
Upvotes: 1
Reputation: 279255
Your definition of class Student { ... }
shouldn't compile either. The friend
declaration is an error, so I'm surprised that isn't highlighted too. What your IDE has figured out is that the access to a private member isn't allowed without a working friend
declaration.
The error is that a forward declaration of Klasa
is not enough to declare a member function of Klasa
to be a friend of Student
. You need the class definition of Klasa
first.
So, it should be:
class Student; // forward declaration, because members of Klasa take Student*
class Klasa {
...
};
class Student {
...
};
then you can define Klasa::assignToKlasa
.
Upvotes: 4