-4

4 classes: Creature, Vampire, WereWolf, VampireWerewolf.

In each one we have a function called printInfo that prints the relevant info of the class.

Example: In Creature, it prints name, age. Vampire prints sunlightSensetivity, wereWolf prints wolfHours, manHours etc. I have an object of class VampireWerewolf, if I will call printInfo, the Creature Part will be called twice and I want it to be printed only once.

A R
  • 1,412
  • 2
  • 14
  • 29
  • 4
    Instead of describing your code, *show it*. Please [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask), and learn how to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). – Some programmer dude Oct 24 '17 at 17:07
  • Please post your code and explain in more detail for us to help you understand the problem. – A R Oct 24 '17 at 17:07
  • Look at [decorator pattern](https://en.wikipedia.org/wiki/Decorator_pattern) as alternative to multiple inheritance in your case. – Jarod42 Oct 24 '17 at 17:19

3 Answers3

1

The solution in short:
create a protected implementation of printInfo in both Vampire and WereWolf classes (printOnlyVampire, printOnlyWereWolf) and call them from VapmireWereWolf.

Explanation

I happen to know what the original question is so here are the 4 classes:

class Creature {
  /** has some creature properties */
  public: 
    virtual void printInfo() {
      /** print all creature properties... */
    }
}

class Vampire: virtual public Creature {
 /** has some Vapmire specific properties */
  public: 
    virtual void printInfo() {
      /** print all of the creature properties */
      Creature::printInfo();
      /** print all Vampire properties... */
    }
}

class WereWolf: virtual public Creature {
 /** has some WereWolf specific properties */
 public:
    virtual void printInfo() {
      /** print all of the creature properties */
      Creature::printInfo();
      /** print all WereWolf properties... */
    }
}

class VapmireWereWolf: public Vampire, public WereWolf  {
 /** has some VapmireWereWolf specific properties */
 public:
    virtual void printInfo() {
      /** print all of the Creature + Vampire properties */
      Vampire::printInfo();
      /** print all of the Creature + WereWolf properties */
      WereWolf::printInfo();
      /** print all VapmireWereWolf properties... */
    }
}

The problem

In the current implementation, calling the VapmireWereWolf class printInfo function will cause the Creature class properties to be printed twice.
Both Vampire and WereWolf are calling Creature::printInfo() in their printInfo implementation, but we can't change that because we still need them printed in case we have an object of type Vampire/WereWolf and we want all of his properties printed.

The solution

Create a protected function for Vampire and WereWolf which only print's their own info, and call it from VapmireWereWolf.

class Vampire: virtual public Creature {
 /** has some Vapmire specific properties */
  public: 
    virtual void printInfo() {
      /** print all of the creature properties */
      Creature::printInfo();
      printOnlyVampire();
    }
  protected:
    void printOnlyVampire() {
      /** print all Vampire properties... */
    }
}

class WereWolf: virtual public Creature {
 /** has some Vapmire specific properties */
  public: 
    virtual void printInfo() {
      /** print all of the creature properties */
      Creature::printInfo();
      printOnlyWereWolf();
    }
  protected:
    void printOnlyWereWolf() {
      /** print all WereWolf properties... */
    }
}

class VapmireWereWolf: public Vampire, public WereWolf  {
 /** has some VapmireWereWolf specific properties */
 public:
    virtual void printInfo() {
      /** print all of the creature properties */
      Creature::printInfo();
      /** print all of the Vapmire properties */
      Vampire::printOnlyVampire();
      /** print all of the WereWolf properties */
      WereWolf::printOnlyWereWolf();
      /** print all VapmireWereWolf properties... */
    }
}
Shahar Kazaz
  • 1,146
  • 1
  • 9
  • 21
0

Without code I can only assume what you are asking, but I'll give it a shot. I believe that your code is structured like this.

class Creature
{
    public:
        void printInfo()
        {
              //Print Creature info
        };
};

class Vampire : Creature
{
    public:
        void printInfo()
        {
              //Print Vampire info
        };
};

class WereWolf : Creature
{
    public:
        void printInfo() 
        {
            //Print info
        };

class VampireWereWolf : WereWolf
{
    private:
        Vampire vp;
    public:
        void printInfo()
        {
            // Print info of both vampire and werewolf
        };
};

I would recommend you to turn the PrintInfo method into a virtual method. This would allow each class to override it with the most appropriate implementation. Only one PrintInfo would be called, but it would handle VampireWereWolf correctly.

  • thank you for your answer but I have 2 problem with what you wrote 1. the VampireWereWolf only inherits from werewolf, it needs to inherit from both werewolf and vampire 2. even after it the problem would be that the creatures members would be printed twice, once for werewolf and once fro vampire – adam baranes Oct 25 '17 at 13:12
  • I think this post will point you into the right direction. [It covers diamond inheritance.](https://stackoverflow.com/questions/2659116/how-does-virtual-inheritance-solve-the-diamond-multiple-inheritance-ambiguit). Setting the printInfo() function as virtual in the Creature class should fix the issues you are having. – GravityManiak Oct 25 '17 at 18:30
0

With decorator pattern, you may do something similar to:

class Creature
{
public:
    Creature(const std::string& name) : name(name) {}

    virtual ~Creature() = default;
    virtual void printInfo() const
    {
        std::cout << name;
    };

    std::string name;
};

template <typename T>
class VampiredCreature : T
{
public:
    VampiredCreature(const T& t, float sunlightSensitivity)
    : T(t),
      sunlightSensitivity(sunlightSensitivity) {}

    void printInfo() const override
    {
        T::printInfo();
        std::cout << " vampired: " << sunlightSensitivity;
    };
    float sunlightSensitivity = 0.f;
};

template <typename T>
class WereWolfCreature : T
{
public:
    WereWolfCreature(const T& t, int wolfHours) : T(t), wolfHours(wolfHours) {}

    void printInfo() const override
    {
        T::printInfo();

        std::cout << " wereWolf: " << wolfHours;
    }
    int wolfHours;
};

using Vampire = VampiredCreature<Creature>;
using Werewolf = WereWolfCreature<Creature>;
using VampireWerewolf = WereWolfCreature<Vampire>;

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302