Document number: Date: Reply to: |
NXXXX 2015/03/22 Dejan D.M. Milosavljevic (dmilos at gmail dot com) |
protected
and private
make limitation of access to class members.friend
make exception to that by granting complete access.
class A{
public:
void set_value( int const& val );
int const& get_value()const;
protected:
void val_internal_set( int const& i );
private:
int int_value;
friend class B;
};
class B {
public:
void val_change( A & a ){
a.val_internal_set( 2 );
a.int_value = 4; //!< We do not want that, but it can be accidentally on this place even with correct effects.
}
};
—end example]B::val_change
, has complete access.
class A{
// ... ... ...
friend class B::val_change;
};
—end example]
A::val_internal_set
.A::val_internal_set
and not to other members.B::val_change
knowing that ( by design ) class B
( or B::val_change
) can access to A::val_internal_set
and not to other members.
friend
s can access or not.
class A{
// ... ... ...
protected:
void val_internal_set( int const& i );
private:
int int_value;
protected:
void float_internal_set( float const& f );
private:
float float_value;
protected:
void string_internal_set( std::string const& s );
private:
std::string string_value;
// B::val_change can use only to val_internal_set and float_internal_set.
friend void B::val_change() >> void val_internal_set( int const& i )
>> void float_internal_set( float const& f );
// C::val_change() can use only to float_internal_set.
friend void C::val_change() >> void float_internal_set( float const& f );
// D::val_change() can not use string_value but can use other members.
friend void D::val_change() !>> string_value;
};
class B {
public:
void val_change( A & a ){
a.val_internal_set( 4 ); //!< OK
a.int_value = 2; //!< Error can not use
}
};
class C {
public:
void val_change( A & a ){
a.float_internal_set( 4 ); //!< OK
a.val_internal_set( 2 ); //!< Error can not use
}
};
class D {
public:
void val_change( A & a ){
a.val_internal_set( 4 ); //!< OK
a.float_internal_set( 2 ); //!< OK
a.string_value = "abc"; //!< Error can not use
}
};
—end example]
class A{
// Access to all protected functions and to string_value
friend class X >> protected !>> string_value;
// Access to all private functions and not to string_value
friend class X >> private !>> string_value;
};
—end example]
friend
friend-specifier ( '>>' friend-member-declaration )zero-or-more ';'friend
friend-specifier ( '!' '>>' friend-member-declaration )zero-or-more ';'class A { public: // ill-formed. Double friend refinement of B::val_change(). friend void B::val_change() >> void val_internal_set( int & i ) friend void B::val_change() >> void float_internal_set( int & i ) ; // OK. This is not refinement. friend class E; friend class E; };—end example]
[Example:class A { // ... ... ... friend void B::val_change() -> val_internal_set( int const& i ) -> void -> float_internal_set( float const& f ) -> void; };—end example]
[Example:class A { // ... ... ... friend void B::val_change() >> void val_internal_set( int const& i ) , void float_internal_set( float const& f ); };—end example]
[Example:Without >> this is more worse. It is look like function definition.class A { // ... ... ... friend void B::val_change() >> { void val_internal_set( int const& i ) , void float_internal_set( float const& f ); } };—end example]
[Example:class A { // ... ... ... friend void B::val_change() { void val_internal_set( int const& i ) , void float_internal_set( float const& f ); } };—end example]
[Example:Without '>>' things look much worse.class A { // ... ... ... friend void B::val_change() >> [ void val_internal_set( int const& i ) , void float_internal_set( float const& f ) ] ; };—end example]
[Example:class A { // ... ... ... friend void B::val_change() [ void val_internal_set( int const& i ) , void float_internal_set( float const& f ) ] ; };—end example]