How do I solve the one-way protection?

  • Permalink
  • submit to reddit
  • Email
  • Follow


Hi!

I want to use the compiler to force correct initialization by forcing 
certain functions to be implemented in the subclasses (pure virtual 
functions only reach the first subclass). In my example below we can 
assume that the base class must be initialized by collecting, say class 
names.

class Base
{
public:
    Base();

protected:
    template<class T>
    void init_()
    {
       std::string cn = static_cast<T*>(this)->getClassName_();
       ... store cn in a list ...
    }
};

class Derived1 : public Base
{
public:
    Derived1() { init_<Derived1>(); }

protected:
    std::string getClassName_() const { return "Number 1"; }
};

class Derived2 : public Derived1
{
public:
    Derived2() { init_<Derived2>(); }

protected:
    std::string getClassName_() const { return "Number 2"; }
};


This does not compile unless I make getClassName_() public. Why is 
protection one-way and how can I get around it?


Thanks,
Daniel

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply DeMarcus 8/6/2009 10:05:54 PM

See related articles to this posting

>    template<class T>
>    void init_()
>    {
>       std::string cn = static_cast<T*>(this)->getClassName_();
>       ... store cn in a list ...
>    }
> [...]
> This does not compile unless I make getClassName_() public. Why is
> protection one-way and how can I get around it?

When you convert "this" to a generic "T*" using static_cast<>, you no
longer benefit from being able to access protected members of T, even if
  T is the class you're calling from. For the simple reason that T can
now be anything, including "int" or "std::string". The compiler will
assume that you know what you're doing and T does have an accessible
(read: public) getClassName_() function, but no more than that.

You really don't need templates at all for what you're doing, that is
you can solve your problem either with templates, but no virtual
functions (in which case your member function needs to be public for the
reasons stated above), or without templates and with virtual member
functions, where you define getClassName_() as pure virtual in Base, and
simply call:

std::string cn = getClassName_();

in init_(). This will call the correct function for your objects.


-- 
Razvan Cojocaru
KeyID: 0x04CA34DE

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Razvan 8/7/2009 12:37:54 PM


On Aug 7, 12:05 am, DeMarcus <use_my_alias_h...@hotmail.com> wrote:
> Hi!
>
> I want to use the compiler to force correct initialization by forcing
> certain functions to be implemented in the subclasses (pure virtual
> functions only reach the first subclass). In my example below we can
> assume that the base class must be initialized by collecting, say class
> names.
>
> class Base
> {
> public:
>     Base();
>
> protected:
>     template<class T>
>     void init_()
>     {
>        std::string cn = static_cast<T*>(this)->getClassName_();
>        ... store cn in a list ...
>     }
>
> };
>
> class Derived1 : public Base
> {
> public:
>     Derived1() { init_<Derived1>(); }
>
> protected:
>     std::string getClassName_() const { return "Number 1"; }
>
> };
>
> class Derived2 : public Derived1
> {
> public:
>     Derived2() { init_<Derived2>(); }
>
> protected:
>     std::string getClassName_() const { return "Number 2"; }
>
> };
>
> This does not compile unless I make getClassName_() public. Why is
> protection one-way and how can I get around it?
>
> Thanks,
> Daniel

I think you've got to declare Base a friend in each derived class.
At least that's what people sometimes do with Curiously Recurring
Template Pattern, and your case is somewhat similar to CRTP.

Note that unless getClassName_ should be called from more
derived classes, you should declare them private, not protected.


HTH,
   Andy.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Andrew 8/7/2009 12:40:44 PM

On 7 Aug, 05:05, DeMarcus <use_my_alias_h...@hotmail.com> wrote:
> Hi!
>
> I want to use the compiler to force correct initialization by forcing
> certain functions to be implemented in the subclasses (pure virtual
> functions only reach the first subclass). In my example below we can
> assume that the base class must be initialized by collecting, say class
> names.
>
> class Base
> {
> public:
>     Base();
>
> protected:
>     template<class T>
>     void init_()
>     {
>        std::string cn = static_cast<T*>(this)->getClassName_();
>        ... store cn in a list ...
>     }
>
> };
>
> class Derived1 : public Base
> {
> public:
>     Derived1() { init_<Derived1>(); }
>
> protected:
>     std::string getClassName_() const { return "Number 1"; }
>
> };
>
> class Derived2 : public Derived1
> {
> public:
>     Derived2() { init_<Derived2>(); }
>
> protected:
>     std::string getClassName_() const { return "Number 2"; }
>
> };
>
> This does not compile unless I make getClassName_() public. Why is
> protection one-way and how can I get around it?

There are two issues here: Why is protection one way? and How to get
the class name in the base class constructor?

Why is protection one way?
(A) I would think that most people would consider it unnatural to
allow special access to base classes. After all a base class is not
supposed to depend on the declaration of its derived classes (Although
it can depend on the definitions using virtual methods).
(B) What would you expect from:  Derived2()
{ init_<CompletelyUnrelated>(); }
(C) In general it is not valid to call ANY derived class member
function from a base class constructor because the derived object is
not constructed at that point. (This is why virtual methods aren't
virtual in a constructor)

How to get that class name to the base class constructor:
Short answer: Provide a protected constructor in the base class that
takes it as parameter.
Note that you never NEED to call a derived class member in a base
class constructor because it can never return anything that couldn't
have been passed as a parameter.
Occasionally it can be useful to have a STATIC derived class function
to compute the constructor parameter if this is complex.
In this specific example there is no reason for getClassName_ to not
be static as it does not depend on object state:

cn = T::getClassName_();


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Nick 8/7/2009 12:41:39 PM
comp.lang.c++.moderated 10583 articles. 6 followers. Post

3 Replies
117 Views

Similar Articles

[PageSpeed] 27


  • Permalink
  • submit to reddit
  • Email
  • Follow


Reply:

Similar Artilces:

Can you solve my one way ping problem ?
OS=Win2K Pro When "Deterministic Network Enhancer" is loaded, I can ping other machines on the LAN by IP, but they can't ping me. If I uninstall this service and reboot, all is well. When it is installed, no one can ping me even if I don't check the boxes to make the service inacative for the adapter. Unfortunately, the Cisco VPN that I use on the road requires that this service be installed. Any clues or ideas (other than uninstalling and installing as required) ? Thanks. GS ...

One Way -- Two Way?
I understand that the Windows XP firewall blocks incoming but not outgoing. If one uses an AV program and one or more spyware/malware programs, Is the One-Way Windows XP firewall adequate? Thanks for advice/opinions Carl On Tue, 9 Nov 2004 17:09:53 -0700, Carl spoketh >I understand that the Windows XP firewall blocks incoming but not outgoing. >If one uses an AV program and one or more spyware/malware programs, >Is the One-Way Windows XP firewall adequate? > >Thanks for advice/opinions >Carl > If you have anti-virus software, and scan your system for spyware every so...

Both way and one way relationships
hello My book claims there are two kinds of relationships: Two way connection and one way connection, but it doesn't go into any more details. Anyways, here are the graphical representations that my book uses for displaying two way and one way relationships: <<---------->> //this is two way many-to-many connection <------------>> // this is two way one-to-many connection -------------->> // this is one way one-to-many connection At first I thought that one way connection would be between primary key in a row and all other no...

One-to-Many Corba one-way call
Hi all, I have read somewhere that it is possible to call a method on every instance of an object (one-to-many call on a group); my application is a distibuted system, and I want objects on remote nodes to all act the same. I would have no return value on those calls. From the material I have read so far, it also seems possible to use multi-cast or broadcast protocols (eg UDP) to distribute those one-to-many calls. Is this possible using TAO ? Can someone point me to ressources (articles or samples) going in that direction ? Any previous experience and comment would be nice, Thanks Jul...

Shortest way to read all lines (one by one) from a text file?
Ok, I know in general a way to read text lines ony-by-one from a file into a string variable. But I miss somehow a short one-liner like: foreach(String currentline : file("D:\test\myfile.txt")) { .... } Is there something like this in Java? What would be the shortest way otherwise? Robin On 2/11/11 4:20 PM, Robin Wenger wrote: > Ok, I know in general a way to read text lines ony-by-one from a file into a string variable. > But I miss somehow a short one-liner like: > > foreach(String currentline : file("D:\test\myfile.txt&qu...

there is more than one way to do it...
Unfortunately, I never remember any. Luca On Dec 5, 10:37=A0pm, luca <luca_rem...@alice.it> wrote: > Unfortunately, I never remember any. > > Luca Learn (at least READ) all the ways, and remember the easiest ;-) ...

Solve this one
Know someone who wants to set up two clients coming off a server (via wireless NICs). This server will be attached to a cable modem and the problem is he was told that since he doesn't have a static IP that the clients will eventually come up with unable to connect when browsing Internet. They said its impossible for these clients to stay on unless he purchases a perm. IP address for 79.00 /month. Any ideas out there? Also if you can recommend a Cisco router or similar device that will work around this. Doesn't have a lot of money since its for home. Thanks for any input. In ...

There's Gotta Be A Better Way #3: To One Or Not To One
So I want 1 or -1 at random. This looks verbose: (- 1 (* 2 (random 2))) Thoughts? ken -- Algebra: http://www.tilton-technology.com/LispNycAlgebra1.htm "Well, I've wrestled with reality for thirty-five years, Doctor, and I'm happy to state I finally won out over it." -- Elwood P. Dowd "I'll say I'm losing my grip, and it feels terrific." -- Smiling husband to scowling wife, New Yorker cartoon Ken Tilton <kentilton@gmail.com> writes: > So I want 1 or -1 at random. This looks verbose: > > (- 1 (* 2 (random 2))) > > Th...

tcp/ip network: one way ping on one machine
I have a local network with 3 machines running XP Pro. All machines can communicate with each other and the Internet. They can even see each other in the Network Places screen. Here is the issue: I can ping from everywhere to anywhere except one machine which will not accept a ping but can send one out to anywhere and get a response. When I try to ping that machine with its own IP address it times out. Not the case with the other two machines that respond properly. This particular machine sees everyone else in the Explorer, Network Places and the like but cannot respond to any...