I want to make an inner class a friend of an unrelated class but this doesn't seem to work (at least in gcc 4.1.2):
class A {
int i;
friend class B; // fine
friend class B::C; // not allowed?
};
class B {
int geti(A* ap) { return ap->i; }
class C {
int geti(A* ap) { return ap->i; }
};
};
You have to declare B::C before using it. The following might work.
Update: Ignoring a usable demonstration as requested, here's a way of structuring this (minus the definitions of member functions) that could work, but bear in mind that everything is private as it stands.
class A;
class B
{
int geti(A * ap);
public:
class C
{
int geti(A * ap);
};
};
class A
{
friend class B; // fine
friend class B::C; // fine too
int i;
};
Then define the getter functions elsewhere:
int B::geti(A * ap) { ... }
int B::C::geti(A * ap) { ... }
Alternative: forward-declare the nested class B::C and save one external definition:
class A;
class B
{
int geti(const A * ap) const; // we cannot use A yet!
public:
class C;
};
class A
{
friend class B; // fine
friend class B::C; // fine too
int i;
};
int B::geti(const A * ap) const { return ap->i; }
class B::C
{
inline int geti(const A * ap) const { return ap->i; }
};
Related
How do I change the int 'a' inside class A but restrict the function that changes the int to ONLY class B? I do not even want A to be able to change it.
I have tried to create a friend function, but I get an error I included in the comments of the code. I then tried to just forward declare the function as a friend function in private and then actually creating the function in public, but the C class can access the public function. This despite me writing (in the private section) that the function is a friend function. Can I 'friend' a private value? I am unsure what to do here.
#include <stdio.h>
#include <iostream>
int main() {
// forward declaration
class B;
class C;
class A {
private:
int a; // private member I want to edit, but only via class B.
int a2; // I would like to NOT be able to access this in class B. I only want to access and modify int a from class B, no other variable. If possible.
// invalid use of non-static data member 'a'
friend void test(int new_value) {
a = 5;
}
friend B;
public:
};
class B {
private:
int b;
public:
change_a_value(A a_class, int new_int) {
a_class.test(new_int); // I want this to be possible.
}
};
class C {
private:
int c;
public:
change_a_value(A a_class, int new_int) {
a_class.test(new_int); // I want this to be impossible
}
};
return 0;
}
Add "void" before prototypes of change_a_value, and change the
friend B
to
friend class B
and suppress friend in
friend void test(int new_value) {
complete corrected program :
int main() {
// forward declaration
class B;
class C;
class A {
private:
int a; // private member I want to edit, but only via class B.
int a2; // I would like to NOT be able to access this in class B. I only want to access and modify int a from class B, no other variable. If possible.
void test(int new_value) {
a = new_value;
}
friend class B;
public:
};
class B {
private:
int b;
public:
void change_a_value(A a_class, int new_int) {
a_class.test(new_int); // I want this to be possible.
}
};
class C {
private:
int c;
public:
void change_a_value(A a_class, int new_int) {
a_class.test(new_int); // I want this to be impossible
}
};
return 0;
}
Compilation results are what was expected :
TestCpp2.cpp:9:14: error: ‘void main()::A::test(int)’ is private
void test(int new_value) {
^
TestCpp2.cpp:28:31: error: within this context
a_class.test(new_int); // I want this to be impossible
^
Makefile:510: recipe for target 'TestCpp2.o' failed
make: *** [TestCpp2.o] Error 1
I am dealing with a situation where I am trying to define two classes that are dependent on each other. This is a simplified example of what I am trying to do.
class a{
public:
int ia;
int printb(b in){
return in.ib;
}
};
class b{
public:
int ib;
int printb(a in){
return in.ia;
}
};
This gives me undefined class b errors. I have tried
class b;
class a{
public:
int ia;
int printb(b in){
return in.ib;
}
};
class b{
public:
int ib;
int printb(a in){
return in.ia;
}
};
But that does not fixed the problem. Any ideas?
All you have to do is to keep the implementation of the member functions outside the class definition. You can then ensure that both classes are defined before implementing the members:
class b;
class a{
public:
int printb(b in);
int ia;
};
class b{
public:
int ib;
int printb(a in);
};
int a::printb(b in){
return in.ib;
}
int b::printb(a in){
return in.ia;
}
I'm currently reading C++ Primer and am at the point of class friends and member function friends and I'm having trouble figuring out how to get the code that has the following pseudoform to work:
class B;
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction(Args); // Compile error: Incomplete Type
};
class B {
public:
void someMemberFunction(Args) { /* doStuff */ }
private:
vector<A> someVector { A(5) };
};
If you try to compile in this form it gives the incomplete type error on the friend line. So the solution is to move the class B definition above class A:
class A;
class B {
public:
void someMemberFunction(Args) { /* doStuff */ }
private:
vector<A> someVector { A(5) }; // Compile error: Incomplete Type
};
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction(Args);
};
However now on the vector line, it doesn't know how to create an object of type A, since A has yet to be defined. So then A needs to be defined before B. But now we've arrived back at the original problem. I think this is called circular dependency? I don't know how to fix this with forward declarations.
Any help would be appreciated. Thanks.
I think you will either have to make the whole of class B a friend (which removes a dependency in A anyway so it's probably a good thing), or use a constructor instead of the in-class initializer.
class B;
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend class B;
};
class B {
public:
void someMemberFunction() { /* doStuff */ }
private:
vector<A> someVector { A(5) };
};
Or this
class A;
class B {
public:
B();
void someMemberFunction() { /* doStuff */ }
private:
vector<A> someVector;
};
class A {
public:
A(int i): someNum(i) { }
private:
int someNum;
friend void B::someMemberFunction();
};
B::B(): someVector{A(5)} { }
I obtain a error: 'func' does not name a type when a member function func of a class B attempts to return a class C:
class A {
public:
class B {
public:
C func() const {
...
}
private:
friend class A;
}
class C {
public:
...
private:
friend class A;
}
private:
...
}
Whereas, if func is a member function of A, then the following does not produce this error:
class A {
public:
class B {
public:
...
private:
friend class A;
}
C func() const {
...
}
class C {
public:
...
private:
friend class A;
}
private:
...
}
How can I fix it to make the first version work?
I found a great example here.
Define class C "above" class B, or forward declare it.
I want a type A that will yield its hidden datum to an object of type T but hide the datum from everyone else. My C++ compiler happens to be GCC 4.4, but that shouldn't matter. Why won't this work?
#include <iostream>
template <class T> class A {
private:
int n1;
public:
friend class T;
A(const int n0 = 0) : n1(n0) {}
};
class B {
public:
int f(const A<B> a) const { return a.n1; }
B() {}
};
int main() {
const A<B> a(5);
const B b;
const int m = b.f(a);
std::cout << m << "\n";
return 0;
}
Incidentally, this works fine, except that it fails to hide the datum:
#include <iostream>
template <class T> class A {
private:
int n1;
public:
int n() const { return n1; }
A(const int n0 = 0) : n1(n0) {}
};
class B {
public:
int f(const A<B> a) const { return a.n(); }
B() {}
};
int main() {
const A<B> a(5);
const B b;
const int m = b.f(a);
std::cout << m << "\n";
return 0;
}
Does C++ really not allow a friend class to be specified at compile time as a template parameter? Why not? If not, then what alternate technique should I use to hide the datum? (One would prefer a compile-time technique if possible.)
What is my misunderstanding here, please?
(I see some answers to related questions here and here, but either they don't answer my particular question or I fail to understand that they do so. At any rate, maybe I am using the wrong technique altogether. Though I remain interested in why the friend class T fails, what I really want to know is how to hide the datum, whether with a friend or by other means.)
Thanks.
Your compiler is simply too old. C++11 allows you to declare template parameters as friends.
§11.3 [class.friend] p3
A friend declaration that does not declare a function shall have one of the following forms:
friend elaborated-type-specifier ;
friend simple-type-specifier ;
friend typename-specifier ;
If the type specifier in a friend declaration designates a (possibly cv-qualified) class type, that class is declared as a friend; otherwise, the friend declaration is ignored.
And it even contains an example of a template parameter as a friend:
class C;
// [...]
template <typename T> class R {
friend T;
};
R<C> rc; // class C is a friend of R<C>
R<int> ri; // OK: "friend int;" is ignored
C++03 sadly has no way to do this, however you can simply friend a single free function and let that act as "glue" code that takes the data from one class and passes it to the other. Another way might be the passkey pattern.
I don't know the standardese behind your error (refer to Xeo's answer), but I did find a workaround for C++03.
Instead of making T a friend, make one of T's member functions a friend:
#include <iostream>
template <class T> class A {
private:
int n1;
public:
friend int T::getN1(const A& a) const;
A(const int n0 = 0) : n1(n0) {}
};
class B {
public:
int f(const A<B> a) const { return getN1(a); }
B() {}
private:
int getN1(const A<B>& a) const {return a.n1;}
};
class C {
public:
int f(const A<B> a) const { return getN1(a); }
C() {}
private:
// Error, n1 is a private member of A<B>
int getN1(const A<B>& a) const {return a.n1;}
};
int main() {
const A<B> a(5);
const B b;
const int m = b.f(a);
std::cout << m << "\n";
return 0;
}
Alternatively, you can make a nested class/struct of T be a friend of A. This may be more convenient if there are several private members of A that you want T to have access to.
#include <iostream>
template <class T> class A {
private:
int n1;
public:
friend class T::AccessToA;
A(const int n0 = 0) : n1(n0) {}
};
class B {
public:
int f(const A<B> a) const { return AccessToA::getN1(a); }
B() {};
private:
friend class A<B>;
struct AccessToA
{
static int getN1(const A<B>& a) {return a.n1;}
};
};
class C {
public:
int f(const A<B> a) const { return AccessToA::getN1(a); }
C() {};
private:
friend class A<C>;
struct AccessToA
{
// Error, n1 is a private member of A<B>
static int getN1(const A<B>& a) {return a.n1;}
};
};
int main() {
const A<B> a(5);
const B b;
const int m = b.f(a);
std::cout << m << "\n";
return 0;
}