• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 309
  • Last Modified:

c++; inheritence; multiple? or perhaps a better solution?

I think maybe I'm going about my coding needs the wrong way, but I'm kind of in a rut and cannot seem to think outside the box at the moment.  Perhaps someone could either help me to fix my code or suggest a better alternative?  I'd really appreciate some aide.

I have a base class, ABase.  This class has a map<string,string>* parameter, and a few others, too.   This base class handles the setting/getting of the other parameters, and only generic access to the map (i.e. it gets a list of all keys, gets a list of all values, etc).  

Next, I define a derived class, ABaseCore, which targets specific key names to be used in the ABase->attrs.  It doesn't add any new parameters, it simply provides a convenient set of methods for setting/getting some parameters I consider core attributes.

Then, I define another derived class ABaseExtra, which does pretty much the same thing as ABaseCore, but different named methods for specific parameters.

There are about 3 or 4 other derived classes, which all have their own unique methods for handling specific parameters.  I'll skip the code on those, since they are pretty much the same thing as ABaseCore and ABaseExtra.

Now, the intent is to derive new classes from several of the previously derived classes (such as ABaseCore) - this is so my new classes have a nice collection of convenient-to-use method names which target the specific parameters.

Now, I understand the dynamics of referring to the base class in an unambiguous way.  part of the problem, however, is that I want the base class to have an overloaded operator<< which will output any of the higher level derived classes (such as ABC and DEF), but I can't quite figure out how to make it work.  I keep getting the error:

ambiguous conversions from 'ABC' to 'ABase &'

on the code:
ABC *a = new ABC();

cout << (*a)  << endl;

I have a feeling there is a better way to accomplish what I'm trying to do, but I've been staring at this code for about an hour and I think my brain will implode soon.  

I could simply forgo the 2nd-level of derivation, and simply put all the methods (from ABaseCore, etc) right into ABC, etc...  but that would be a lot of duplicate code... not every derived class will require the ABaseCore methods and not every derived class will require the ABaseExtra, but enough do that having a re-usable code segment makes sense.

Please, I beseech thee, aide!
//  base class
class ABase
{
 private:
  string p1;
  string p2;
  map<string,string> *attrs;
 
public:
  ABase()  { this->attrs = new map<string,string>; }
  ~ABase() { delete this->attrs; }
 
  void set(string key, string value) { (*this->attrs)[key] = value; }
 
  // code for p1 and p2 left out intentionally
 
  vector<string> *getKeys()       {  ...  }  //  truncated
  vector<string> *getValues()     {  ...  }  // for the sake
  string          get(string key) {  ...  }  // of brevity
  string          str() { ...  // convert the attrs into a string list }
 
  friend ostream &operator<<(ostream &strm, ABase &base) {
    strm << base.str();
    return strm;
  }
};
 
//  derived classes from the base
class ABaseCore : public ABase
{
public:
  void   setName(string newName) { this->set("name", newName); }
  string getName()               { return this->get("name");   }
 
  void   setType(string newType) { this->set("type", newType); }
  string getType()               { return this->get("type");   }
};
 
 
class ABaseExtra : public ABase
{
public:
  void   setFamily(string newFamily) { this->set("family", newFamily); }
  string getFamily()                 { return this->get("family");   }
 
  void   setGenus(string newGenus)   { this->set("genus", newGenus); }
  string getGenus()                  { return this->get("genus");   }
};
 
 
//  using collections of derived classes
class ABC : public ABaseCore, public ABaseExtra
{
  //  now this class has all the methods defined in all derived classes
};
 
class DEF : public ABaseCore, public ABaseSpecial, public ABaseID
{
  //  assume that ABaseSpecial and ABaseID are defined just like ABaseCore and ABaseExtra
};

Open in new window

0
BaconU
Asked:
BaconU
4 Solutions
 
link64Commented:
I havent played with c++ for a while, but have you tried doing:

ABase *abc = new ABC();
cout << (*a)  << endl;

Make the pointer of type ABase, but instantiate the ABaseCore ...
0
 
jhshuklaCommented:
0
 
BaconUAuthor Commented:
link64:  It won't work like that, simply due to the fact that ABase and ABC are not directly linked.  Now, I could say:

ABaseCore *abc = new ABC();

and that would work...  but then I lose the functionality of not only the other inherited classes (ABaseExtra, etc) but also the ABC-specific methods.   It is a good thought, though.

jhshukla:  That does answer the basic question of, how does one access the base members in an inherited class, especially one who has multiple levels of inheritence.  However, the problem of ambiguity still remains.  Supposing the ABase class contains a method "add(string text)"...   ABaseCore and ABaseExtra both inherit this method from ABase.  And now ABC inherits both ABaseCore and ABaseExtra, which has thus inherited two different sets of ABase.   As a result, ABC now contains two different inherited "add(string text)" methods.  

   Subsequent calls to the "add()" method on ABC have to know which sub-ABase is being referenced.

  I could say something like:

ABC *abc = new ABC();
abc->ABaseCore::add("blah");

  This does work.   But, supposing class GHI does not inherit ABaseCore, but ABaseExtra?   But now I have to remember to say:

ghi->ABaseExtra::add("blah");

  This is fine, except that it defeats the whole purpose of inheriting.  The point is to provide a common support structure, a foundation, which provides the most basic methods required to make the inheritors, and I (as the programmer) don't need to worry about which class inherits what, at least for the basic stuff.  

  I hope this makes sense.  

  I know that java doesn't allow multi-inheritance and probably for these very kind of issues. :)  

  I would like to add that I'm not even saying the way I'm doing this is correct.  If there is a more eloquent solution, I'd be happy to consider it..   and, and I bumped the points up to the max, in the hopes that a solution can be found.  In the meantime, I'll continue tinkering with the code. :)
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
BaconUAuthor Commented:
point bump
0
 
itsmeandnobodyelseCommented:
You need to derive virtually inorder to have only *one* ABase instance for the ABC objects. Then you have

                     ABase
                 /                    \
        ABaseCore      ABaseExtra
                 \                  /
                        ABC

and not

           ABase             ABase
               |                      |
        ABaseCore      ABaseExtra
                 \                  /
                        ABC

what leads to the ambiguouty.
0
 
itsmeandnobodyelseCommented:
@#!!*#;

It seems that my code snippet was gone as I didn't check the code snippet checkbox.
//  using collections of derived classes
class ABC : virtual public ABaseCore, virtual public ABaseExtra
{
  //  now this class has all the methods defined in all derived classes
};
 

Open in new window

0
 
itsmeandnobodyelseCommented:
Note, virtual derivation is not the key for any mapping problem.

You always should be aware that any public derivation is an "IS A" relation, e. g. for an  ABC object it should be correct to say "it is an ABase",  "it is an ABaseCore" and "it is an ABaseExtra". If one of these statements is not quite true, it would be better you define all functions virtually in ABase and derive only from one of ABaseCore or ABaseExtra (or from ABase directly) and reimplement the functions again.

0
 
BaconUAuthor Commented:
itsme:  I admit the "virtual" keyword gives me a little confusion in the cranial area.  

After first testing the example given by you, the ambiguity was not resolved when calling methods from ABC defined in ABase.  However, when I changed the ABaseCore definition to:

class ABaseCore  : virtual public ABase

.. and the same for the other classes derived directly from ABase, now it does not complain about ambiguity.

  So, it looks like the solution!  Yay!  I will of course do some reading up and research on the virtual keyword so that I may utilize it appropriately. :)

  Thanks!

0
 
BaconUAuthor Commented:
As I noted in my comment to the thread, the 'virtual' keyword needed to be placed on the first derivation of ABase.  This seems to have solved the ambiguity.
0
 
itsmeandnobodyelseCommented:
>>>> class ABaseCore  : virtual public ABase
Yes, of course.

I used the virtual derivation only a few times within decades, so I always have some problems to find the right classes to which to place the virtual keyword to ;-)
0
 
itsmeandnobodyelseCommented:
Looking at my 'graphics' it should get clear:

The compiler needs to know that for the ABaseCore part and the ABaseExtra part used in ABC it should use only one part of ABase. Hence it needs the virtual keyword where the relation to ABase was defined.

In memory you would have

[ABase members][ABaseCore members][ABC members]
[ABaseExtra members]

ABC, ABaseCore, ABase (normally) share the same pointer, while the ABaseExtra has a different pointer.
0

Featured Post

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now