简体   繁体   中英

How to Correct the Polymorphism

I have the following code.

#include <iostream>

class Base1
{
public:

  void print(){std::cout<<"Printing Base1\n";}
};


class Derived1: public Base1
{
public:
  void print_1(){std::cout<<"Printing Derived1 \n";}
};



class Base2
{
public:
  void myFunction1( Base1& b1)
  {
    myFunction2(b1);

  }

  virtual void myFunction2( Base1& b1)
  {
    b1.print();
  }
};

class Derived2: public Base2
{
public:
  void myFunction2( Derived1& d1)
  {
    d1.print_1();
  }
};





int main()
{
  Base1 b1;
  Derived1 d1;
  Base2 b2;
  Derived2 d2;
  b2.myFunction1(b1);
  d2.myFunction1(d1);
  return 0;
}

It results in the following output:

Printing Base1
Printing Base1

I thought of getting the following output

Printing Base1
Printing Derived1

One of the ways to get the desired output is to do the following.

class Derived2: public Base2
    {
    public:
      void myFunction2( Base1& b1)
      {
        Derived1* d1 = static_cast<Derived1*> (&b1);
        d1.print_1();
      }
    };

I would like to allow Derived2 to only deal with Derived1 and not with Base1. Otherwise, Some user may call Derived2::myFunction2 with Base1 object which can crash the program in such cases.

Is there a good solution?

myFunction2() in Derived2 does not override myFunction2() in Base2 .

A virtual function gets overridden only if its signature matches, exactly. The function in this derived class takes a different parameter than the one in the base class. Hence, it does not override.

You have to make it override, as your first step.

class Derived2: public Base2
{
public:
  void myFunction2( Base1& d1) override;
};

Now it's overridden. If you explicitly specified the override qualifier, as I did here, your compiler would've yelled at you already.

Now, your goal is to have whatever myFunction2 does, only have it take in effect for Derived1 class, and for all other Base1 classes, use what the superclass does.

Ok. This will require a little bit more work, and it will be slightly difficult to follow along. What needs to happen is another virtual inheritance, in Base1 this time:

class Derived2: public Base2
{
public:
  void myFunction2( Base1& d1) override
  {
      d1.print_from_Derived2( *this );
  }
};

Now, you need to define Base1::printDerived2() , which will invoke print() , which is what should happen in this case, according to your question:

class Base1
{
public:
       virtual void print_from_Derived2( Derived2 &)
       {
              print();
       }
};

And now, override it in Derived1 in order to put the last piece of the puzzle together:

class Derived1 : public Base1
{
public:
       void print_from_Derived2( Derived2 &) override
       {
              // Do whatever print() from Derived2 needs to do, for
              // this object, which is Derived1.
       }
};

And here, you will do whatever needs to be done for Derived2 to print only Derived1 . It's a bit of a circuitous route, but you finally reached the place where both actors are Derived1 and Derived2 , without breaking any rules, and without any ugly casts.

You will need to do a bunch of forward declarations here, in order to stitch together all of these moving pieces. My examples are just brief simplifications, and they obviously have mutual references to each one, and will have to be broken apart into separate declarations and definitions, with appropriate forward declarations.

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