简体   繁体   中英

c++ - multiple inheritance , how to print a part of a common ancestor only once

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.

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... */
    }
}

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM