Re: Can't take pointer-to-member of protected member of base class
Hello Alf!
Thank you. This is food for thought and very helpful.
On Mar 20, 7:08 pm, "Alf P. Steinbach" <alf.p.steinbach
+use...@gmail.com> wrote:
On 17.03.2012 16:29, K. Frank wrote:
...
pm_test.cpp:6: error: 'int pm_base::m' is protected
pm_test.cpp:13: error: within this context
...
protected: // compiles if m is public
int m; // this is line 6
...
virtual void assign_pm() { pm =&pm_base::m; } // this i=
s line 13
...
An instance of a derived class does have full access to the public and
protected members of any accessible base class part of itself.
The ideal, to prevent "hacks"...
...
This rule does not prevent intentional hacking. It is only about
inadvertent (and then usually disastrous) access. As example, let's
intentionally hack into the protected member "c" of a "std::stack", by
just a little friendly static_cast'ing.
...
<code>
#include <iostream> // std::wcout, std::endl
#include <stack> // std::stack
#include <utility> // std::begin, std::end
using namespace std;
typedef stack<int> Stack;
typedef Stack::container_type Container;
Container const& containerOf( Stack const& st )
{
struct Hack: Stack
{
static Container const& container( Stack const=
& st )
{
return static_cast<Hack const&>( st ).=
c;
}
};
I expect that this hack would work on most (all?) implementations.
But isn't it the case -- please correct me if I'm wrong -- that if
st, the argument to the static cast, refers only to a Stack, but
not, polymorphically, to an actual Hack, then the static cast to
Hack& yields technically undefined behavior?
return Hack::container( st );
}
...
...
For the member pointer your derived class is not allowed to obtain
directly, where it cannot do &Base::x, it can obtain nearly as directly
via &Derived::x.
Yes, this makes sense. As I noted earlier in the thread,
:: I *am* able to
:: take a pointer-to-member of a protected member of the base
class
:: if I do it using a pointer-to-member of the derived class.
:: // this line doesn't compile
:: // virtual void assign_pm() { pm = &pm_base::m; }
:: // this line does
:: virtual void assign_pmd() { pmd = &pm_derived::m; }
And very painlessly. So I think it's just a "language
wart", an undesirable but not very serious consequence of the rules, not
worth special casing to remove.
I am leaning towards the belief that this is a legitimate and
natural consequence (even if somewhat complicated and counter-
intuitive) of how the various rules interact, rather than an
oversight or flaw in the design. But I'm really not sure.
Perhaps there could have been a cleaner design in this corner
of the language.
Cheers & hth.,
- Alf
Thanks again for your explanations and detailed examples.
K. Frank