In C++11 it is possible to make a public member of a private base class accessible to the outside (public) with a using
declaration. For example
class A {
private:
int i = 2;
public:
void f() { i = 3; }
friend bool operator==(const A& l, const A& r) { return l.i == r.i; }
};
class B : private A {
public:
using A::f;
};
int main() {
B b, b2;
b.f();
}
b.f()
is possible because of the using A::f
in the definition of B
.
Is it possible write a similar declaration which would make the up-cast from B&
to A&
possible for the friend function operator==(A&, A&)
, so that b == b2
can be called in main()
?
Friends aren't in the class's scope, and they aren't called using the member-selection operators (. and ->) unless they're members of another class. A friend function is declared by the class that is granting access. The friend declaration can be placed anywhere in the class declaration.
main() can very well be a friend of any class. Just declare it as a friend inside the class like you do for other member functions.
Friend Functions For a free function, it is very straightforward and a forward declaration is not required. We can simply declare the friend as follows: The void Print(const Test& test) function has access to the private members of the Test class. For a member function, it's not as straightforward as the free function.
No, only B
can internally cast itself to A
, and it otherwise is not possible because from a client's perspective B
is not an A
but rather has an A
Even if you replaced your friend bool operator=
with a member function equals
:
class A {
private:
int i = 2;
public:
void f() { i = 3; }
bool equals(const A& r){return i == r.i;}
};
class B : private A {
public:
using A::f;
using A::equals;
};
While this compiles, you cannot ever call b.equals(b2)
because no implicit conversion is ever possible from a type of B
to a type of A
from the caller's perspective (due to private inheritance) .
You'll need to provide your own operator==
or change your inheritance to public
or protected
. Here's an example where B
declares its own friend bool operator==
class B : private A {
public:
using A::f;
friend bool operator==(const B& l, const B& r)
{
return (static_cast<A>(l) == static_cast<A>(r)) && true;
// "true" is a stand-in for some other condition
}
};
Read more at isocpp
Edit:
If you really want to play games, you will notice that I said no implicit conversion is ever possible, but some explicit conversions are. Because B
does technically derive from A
you can do pointer casting to make it work, but I don't recommend it:
class A {
private:
int i = 2;
public:
void f() { i = 3; }
bool equals(const A* r){return i == r->i;}
};
class B : private A {
public:
using A::f;
using A::equals;
};
int main() {
B b, b2;
b.f();
(::A*)(&b)->equals((::A*)(&b2));
}
Or you could use pointer casting's ugly cousin, reference casting, if you wish to keep the original operator==
syntax
class A {
private:
int i = 2;
public:
void f() { i = 3; }
friend bool operator==(const A& l, const A& r) { return l.i == r.i; }
};
class B : private A {
public:
using A::f;
};
int main() {
B b, b2;
b.f();
((::A&)(b)) == ((::A&)(b2));
}
See §11.2 [class.access.base] for more
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With