I ran into an error yesterday and, while it's easy to get around, I wanted to make sure that I'm understanding C++ right.
I have a base class with a protected member:
class Base
{
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
This compiles and works just fine. Now I extend Base but still want to use b:
class Derived : public Base
{
protected:
in开发者_运维技巧t d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
Note that in this case DoSomething
is still taking a reference to a Base
, not Derived
. I would expect that I can still have access to that.b
inside of Derived
, but I get a cannot access protected member
error (MSVC 8.0 - haven't tried gcc yet).
Obviously, adding a public getter on b
solved the problem, but I was wondering why I couldn't have access directly to b
. I though that when you use public inheritance the protected variables are still visible to the derived class.
A class can only access protected members of instances of this class or a derived class. It cannot access protected members of instances of a parent class or cousin class.
In your case, the Derived
class can only access the b
protected member of Derived
instances, not that of Base
instances.
Changing the constructor to take a Derived
instance will solve the problem.
protected
members can be accessed:
- through
this
pointer - or to the same type protected members even if declared in base
- or from friend classes, functions
To solve your case you can use one of last two options.
Accept Derived in Derived::DoSomething or declare Derived friend
to Base:
class Derived;
class Base
{
friend class Derived;
protected:
int b;
public:
void DoSomething(const Base& that)
{
b+=that.b;
}
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b+=that.b;
d=0;
}
};
You may also consider public getters in some cases.
As mentioned, it's just the way the language works.
Another solution is to exploit the inheritance and pass to the parent method:
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
Base::DoSomething(that);
d=0;
}
};
You have access to the protected members of Derived
, but not those of Base
(even if the only reason it's a protected member of Derived
is because it's inherited from Base
)
You can try with static_cast< const Derived*>(pBase)->Base::protected_member ...
class Base
{
protected:
int b;
public:
...
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
b += static_cast<const Derived*>(&that)->Base::b;
d=0;
}
void DoSomething(const Base* that)
{
b += static_cast<const Derived*>(that)->Base::b;
d=0;
}
};
class Derived : public Base
{
protected:
int d;
public:
void DoSomething()
{
b+=this->b;
d=0;
}
};
//this will work
Following the hack for stl I wrote a small code which seems to solve the problem of accessing the protected members in derived class
#include <iostream>
class B
{
protected:
int a;
public:
void dosmth()
{
a = 4;
}
void print() {std::cout<<"a="<<a<<std::endl;}
};
class D: private B
{
public:
void dosmth(B &b)
{
b.*&D::a = 5;
}
};
int main(int argc, const char * argv[]) {
B b;
D d;
b.dosmth();
b.print();
d.dosmth(b);
b.print();
return 0;
}
Prints
a=4
a=5
Use this
pointer to access protected members
class Derived : public Base
{
protected:
int d;
public:
void DoSomething(const Base& that)
{
this->b+=that.b;
d=0;
}
};
精彩评论