1

I have an object of class Message, which can be written and subsequently updated. As far as I can see, MessageUpdate IS-A MessageWrite:

class MessageWrite
{
  protected:
    void setVersion(int version_) {...}
    void setReceiveTime(int tmReceive_) {...}

    Message _msg;
};


class MessageUpdate:public MessageWrite
{
    //ONLY setVersionShould be accessible here, NOT setReceiveTime
};

Is there a combination of method access level and inheritance level that can help achieve this?

I know that MessageUpdate can be simply made base class, but there's the rub: it leads to diamond pattern in case i want to extend the message class. Consider:

class MessageUpdate {...};
class MessageWrite: public MessageUpdate {...};


//Now, while extending:
class AdminMessageUpdate:public MessageUpdate {...};
class AdminMessageWrite: public AdminMessageUpdate, public MessageWrite //DIAMOND Pattern!!

Where'e the gap in my understanding of inheritance? And is there any completely different way to achieve this logic without the multiple inheritance (as shown in latter code piece)?

vidit
  • 957
  • 1
  • 8
  • 23
  • Diamond pattern is OK as long as you are not afraid of [virtual inheritance](http://en.wikipedia.org/wiki/Virtual_inheritance). – Sergey Kalinichenko Apr 09 '12 at 14:10
  • See http://stackoverflow.com/a/21607/13140 for an example of using a virtual base class to ensure you don't get multiple copies of "MessageWrite" in your inheritance tree. So you want ONLY MessageWrite to be able to call setReceiveTime()? – Ogre Psalm33 Apr 09 '12 at 14:15
  • thanks dasblinkenlight, but i would prefer @Als 's method as it saves me the runtime cost of multiple inheritance as well – vidit Apr 09 '12 at 14:16
  • yes Ogre Psalm33. MessageUpdate objects and derivatives should NOT be able to call setReceiveTime() at all – vidit Apr 09 '12 at 14:17

4 Answers4

2

Just declare the method:

private:
void setReceiveTime(int tmReceive_);

with private access specifier in the Base class MessageWrite.

This answer of mine should be a good read:

What are access specifiers? Should I inherit with private, protected or public?

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • thanks, thats spot on. There's no way I can do this automatically? Have to rewrite all methods declarations? – vidit Apr 09 '12 at 14:11
  • @vid: You will have to do that manually. Also, access specifiers for class members are specified in class definition for method declarations.Note that Usually class methods are *declared* in header file and *defined* in the cpp file. – Alok Save Apr 09 '12 at 14:13
1

If MessageUpdate is-a MessageWrite, then by definition, it has access to all of its protected and public members.

So, if there are members that you want publicly/protectedly-exposed in MessageWrite that you don't want exposed in MessageUpdate, then by the Liskov Substitution Principle, MessageUpdate cannot be a MessageWrite.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
1

Since all members of MessageWrite are protected, you could just make setReceiveTime() private inside MessageUpdate, so classes inheriting from MessageUpdate would not be able to access it. But I still have some issues with your design, such as:

How is it that your design avoids the diamond? Wouldn't it equally lead to:

class MessageWrite {...};
class MessageUpdate: public MessageWrite {...};

//Now, while extending:
class AdminMessageWrite:public MessageWrite {...};
class AdminMessageUpdate: public AdminMessageWrite, public MessageUpdate //DIAMOND Pattern!!

Why do you think MessageUpdate IS-A MessageWrite when you later say it is not (by specifying that not all of MessageWrite applies to it)? If this code must not be valid:

MessageWrite& m = MessageUpdate();
m.setReceiveTime(); // Should this be valid?

then MessageUpdate IS-NOT-A MessageWrite. If my code should be valid, then there is no reason to avoid access to setReceiveTime() in MessageUpdate.

And you would probably be better off by creating a base class AdminMessage and then inheriting directly from it to avoid the diamond:

class MessageWrite {...};
class MessageUpdate: public MessageWrite {...};

//Now, while extending:
class AdminMessage {...};
class AdminMessageWrite: public MessageWrite, public AdminMessage {...};
class AdminMessageUpdate: public MessageUpdate, public AdminMessage {...}; // No diamond
Gorpik
  • 10,940
  • 4
  • 36
  • 56
0

protected: inherited members can access.

private: inherited members can not access.

  protected:
    void setVersion(int version_) {...}
  private:
    void setReceiveTime(int tmReceive_) {...}
Alain
  • 26,663
  • 20
  • 114
  • 184