I want to bind() to my base class's version of a function from the derived class. The function is marked protected in the base. When I do so, the code compiles happily in Clang (Apple LLVM Compiler 4.1) but gives an error in both g++ 4.7.2 and in Visual Studio 2010. The error is along the lines of: "'Base::foo' : cannot access protected member."
The implication is that the context for the reference is actually within bind(), where of course the function is seen as protected. But shouldn't bind() inherit the context of the calling function--in this case, Derived::foo()--and therefore see the base method as accessible?
The following program illustrates the issue.
struct Base
{
protected: virtual void foo() {}
};
struct Derived : public Base
{
protected:
virtual void foo() override
{
Base::foo(); // Legal
auto fn = std::bind( &Derived::foo,
std::placeholders::_1 ); // Legal but unwanted.
fn( this );
auto fn2 = std::bind( &Base::foo,
std::placeholders::_1 ); // ILLEGAL in G++ 4.7.2 and VS2010.
fn2( this );
}
};
Why the discrepancy in behavior? Which is correct? What workaround is available for the error-giving compilers?
Protected members that are not declared as static are accessible to friends and member functions in a derived class only through a pointer to, reference to, or object of the derived class.
The code snippet for this is given as follows. class Base { protected : int num = 7; }; class Derived : public Base { public : void func() { cout << "The value of num is: " <<< num; } }; In the function main(), the object obj of class Derived is created. Then the function func() is called.
If a class is derived privately from a base class, all protected base class members become private members of the derived class. Class A contains one protected data member, an integer i . Because B derives from A , the members of B have access to the protected member of A .
A pointer to a directly or indirectly derived class. A reference to a directly or indirectly derived class. An object of a directly or indirectly derived class.
Answer: see boost::bind with protected members & context which quotes this part of the Standard
An additional access check beyond those described earlier in clause 11 is applied when a non-static data member or nonstatic member function is a protected member of its naming class (11.2)105) As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class C. If the access is to form a pointer to member (5.3.1), the nested-name-specifier shall name C or a class derived from C. All other accesses involve a (possibly implicit) object expression (5.2.5). In this case, the class of the object expression shall be C or a class derived from C.
Workaround: make foo a public member function
#include <functional>
struct Base
{
public: virtual void foo() {}
};
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