I have two classes, one and two, each having a friend member function with an pointer to the other. The first header file is as per below:
#ifndef FIRSTCLASS_H
#define FIRSTCLASS_H
class two;
class one {
private:
int one_data;
public:
friend void second_data (two *);
};
#endif
The second header file looks like this:
#ifndef SECONDCLASS_H
#define SECONDCLASS_H
class one;
class two {
private:
int two_data;
public:
friend void first_data (one *);
};
#endif
The actual functions are in a third .cpp file. I wrote the functions with appropriate class qualifier, it gives an compilation error. I am using g++. The functions are as follows:
#include "firstclass.h"
#include "secondclass.h"
void two::first_data (one * class1) {
}
void one::second_data (two * class2) {
}
The errors are as followa:
error:no ‘void two::first_data (one*)’ member function declared in class ‘two’
error: no ‘void one::second_data(two*)’ member function declared in class ‘one’
When I drop the class qualifier before the function name, the code compiles. The modified functions are as follows:
void first_data(one * class1) {
}
void second_data(two * class2) {
}
I am new to c++ and I am not sure if I am doing anything wrong in the first case. Please enlighten me.
What you declare is freestanding functions as friends of your classes.
They are not really members of any class.
friend void first_data (one *);
declares a freestanding function first_data as friend of your class, it does not mean first_data is a member function of your class. Hence when you define the function in cpp file the compiler complains that the function was never declared.
Also,
void two::first_data (one * class1){}
Returntype ClassName ScopeResolution FunctionSignature
two:: tells compiler the functions belongs to this particular class, it is not namespace specification, it is class qualification.
That's not a namespace, that's a class qualifier.
void two::first_data (one * class1) {
}
defines the method first_data from class two.
However, you declared as friend the free function first_data:
friend void first_data (one *);
which is not the same. If you want free functions as friends, use the friend declaration you already have. If not, you can declare methods as friends similary:
friend void two::first_data (one *);
Related
Here is the simple code:
class Outer
{
public:
class Inner
{
static friend void Outer::s_foo(Inner*); //<-- How to declare that?
private:
void inner_foo() {}
};
static void s_foo(Inner * inner)
{
inner->inner_foo();
}
};
Is it possible to declare friendship correctly?
This is a case where order is important. To know s_foo exists, the friend declaration must come after s_foo
class Outer
{
public:
class Inner; // forward declaration to satisfy s_foo's argument
static void s_foo(Inner * inner) // moved ahead of friend declaration
{
inner->inner_foo();
}
class Inner
{
friend void Outer::s_foo(Inner*); //No need for static here. Just need the name
private:
void inner_foo() {}
};
};
As for why s_foo can see inner_foo even though it is declared later, That's just C++ being friendly. When resolving the methods C++ considers the whole class. Why it can't do the same for the friend declaration, frankly I don't know.
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)
I am trying to define a function member of a class Extraction FRIEND with a class Descripteur, but when I compile I get the following error :
*Descripteurs.h:24:57: error: invalid use of incomplete type ‘class Extraction’ friend
void Extraction::globalSet(Descripteurs document);
Descripteurs.h:19:7: error: forward declaration of ‘class Extraction’
class Extraction;*
given by the code :
//in Extraction.h
#include "Descripteurs.h"
class Extraction {
public:
Extraction(Descripteurs document);
void globalSet(Descripteurs document);
protected:
int m_value;
}
// in Extraction.cpp
#include "Extraction.h"
Extraction::Extraction(Descripteurs document){
this->globalSet(document);
}
void Extraction::globalSet(Descripteurs document){
this->m_value = document.m_nbMot; //this is why I need a friend function
cout << this->m_value << endl;
}
//in Descripteur.h
class Extraction; //forward declaration, is there a problem with this ?
class Descripteurs {
public:
friend void Extraction::globalSet(Descripteurs document);
protected:
int m_value;
};
I guess the trouble comes from the fact my classes are imbricated, because Extraction uses Descripteurs and Descripteurs has to know Exctraction to deal with the friend function. I thought the forward declaration was a solution, as explained in how comeforward or c++ friend namespace but I could not find documentation that deal with at the same time friend function, imbricated class and separated files.
and if i remove "Class Extraction;" I get as expected the following error :
‘Extraction’ has not been declared
friend void Extraction::globalSet(Descripteurs document);
friend function over accessor (get functions) is a choice : I don't want to make the attributes accessible from anywhere (in situation the function should take several complex attributes, and not just an int).
Can anyone tell me if I need to add some pieces of code or if there is no way to do this without using accessors ?
Any Help will be welcomed
Thanks
Alexis
Unfortunately, you can't declare a member function of a forward-declared class as friend. See this question for possible workarounds.
This doesn't compile,
#include <boost/intrusive_ptr.hpp>
class X
{
public:
void intrusive_ptr_add_ref(X* blah)
{
}
void intrusive_ptr_release(X * blah)
{
}
};
int main()
{
boost::intrusive_ptr<X> ex(new X);
}
But this does :
#include <boost/intrusive_ptr.hpp>
class X
{
public:
friend void intrusive_ptr_add_ref(X* blah)
{
}
friend void intrusive_ptr_release(X * blah)
{
}
};
int main()
{
boost::intrusive_ptr<X> ex(new X);
}
and this :
#include <boost/intrusive_ptr.hpp>
class X
{
public:
};
void intrusive_ptr_add_ref(X* blah)
{
}
void intrusive_ptr_release(X * blah)
{
}
int main()
{
boost::intrusive_ptr<X> ex(new X);
}
I suppose it has something to do with SFINAE (which I haven't as of yet bothered to understand) ? Does the friend qualifier put the defined function as a free function in the enclosed namespace ?
edit
Whoever removed their post, member functions non-friend as add_ref and release (these specific member functions are not mentioned in the documention...) did solve the problem. What happens with the nested definition with the friend qualifier ?
From the documentation of boost::intrusive_ptr:
Every new intrusive_ptr instance increments the reference count by using an unqualified call to the function intrusive_ptr_add_ref, passing it the pointer as an argument. Similarly, when an intrusive_ptr is destroyed, it calls intrusive_ptr_release; this function is responsible for destroying the object when its reference count drops to zero. The user is expected to provide suitable definitions of these two functions. On compilers that support argument-dependent lookup, intrusive_ptr_add_ref and intrusive_ptr_release should be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace boost.
This means that intrusive_ptr_add_ref and intrusive_ptr_release should not be member functions, but free functions (friend functions behave as such). Furthermore they are called without qualification, so they should be in the global namespace or somewhere found by ADL.
Edit: To your question about nested definitions with friend qualifier:
friend functions are defined as non memberfunctions, so friend void intrusive_ptr_add_ref(X* blah) will be called as intrusive_ptr_add_ref(my_x_ptr) instead of as my_x_ptr->intrusive_ptr_add_ref().
class Base
{
private:
static int num;
public:
friend void setnum(Base obj);
};
void setnum(Base obj)
{
obj.num=4; /* Error */
}
A friend function is supposed to have access to all the private data of a class. what am i missing here? I cant seem to access the the static variable from the friend function.
Error from codepad--> In function
setnum(Base)': undefined reference to
Base::num'
Error from visual studio--> error LNK2001:
unresolved external symbol "private:
static int Base::num"
You only declared the static variable num. You must to define it:
class Base
{
private:
static int num;
public:
friend void setvals(Base obj);
};
// This must be in a .cpp
int Base::num;
void setvals(Base obj)
{
obj.num=4;
}
This code works.
Edit:
Actually you can implement the setvals() function as follows:
void setvals()
{
Base::num=4;
}
And at your Base class:
friend void setvals();
Because num is static.
Your free function is called setvals, but the Base's friend function is called setnum...
Besides you'll have to actually define the static variable, not just declare it.
Put:
int Base::num;
in a source file.
Different friends:
friend void setnum(Base obj);
// ^^^ Not the same as vals!
void setvals(Base obj)
In C++ it's not enough to declare a static variable in the .h; you must also define it explicitly in a .cpp. You must add in the .cpp of the implementation
int Base::num;
What you got was a linker error because of this missing variable definition.
Static variables don't belong to any particular instance of a class. Instead you may access them with a class name as Base::num to improve readability. Also, your friend function definition has a different signature than the one you declared.