0

I can't figure out how to call a base class method from a derived class method but concurrently applying this method call at an object passed as argument.

What I mean is this:

class Animal
{ 
    virtual void eat(Animal& to_be_eaten) = 0;
 };

class Carnivores: public Animal
{ 
    virtual void eat(Animal& to_be_eaten) { /*implementation here*/}

};

class Wolf : public Carnivores
{ 
    virtual void eat(Animal& to_be_eaten)
    { /*call eat method(of Base class) of Base to_be_eaten here*/ }
 }

I thought of something like this

 dynamic_cast<Carnivores&>(to_be_eaten).eat(*this) //and got a segmentation fault

Is there any way for this to be done?

Thank you!

New edit:: Updated the code

Chris
  • 3,619
  • 8
  • 44
  • 64
  • What is the derivation of `Animal`? Is it related in any way to `Base`? – Robᵩ Mar 22 '12 at 18:52
  • If you want it to call the base method and not do anything else, you could just skip the definition in the derived class. – nikhil Mar 22 '12 at 19:01
  • @nikhil: Into the derived eat, there are some conditions that need to be met, in order for the eat of the Base class to be called. – Chris Mar 22 '12 at 19:07
  • @Robᵩ Sorry, just changed it, Animal is the Base. The derived eat will call eat of Base class if some conditions are met (in example if the Animal is hungry). – Chris Mar 22 '12 at 19:08
  • possible duplicate of [C++: How to call a parent class function from derived class function?](http://stackoverflow.com/q/357307/), [How to call Base class method through base class pointer pointing to derived class](http://stackoverflow.com/q/1136249/) – outis Apr 22 '12 at 00:15

2 Answers2

5

As simple as:

class Derived : public Base  {
    virtual void eat(Animal& to_be_eaten) { 
        Base::eat(to_be_eaten);
        // do anything you want with to_be_eaten here.
    }
};

EDIT: This works for me:

class Animal
{ 
    virtual void eat(Animal& to_be_eaten) = 0;
 };

class Carnivores: public Animal
{ 
    virtual void eat(Animal& to_be_eaten) { /*implementation here*/}

};

class Wolf : public Carnivores
{ 
    virtual void eat(Animal& to_be_eaten)
    { 
        Carnivores *c = dynamic_cast<Carnivores*>(&to_be_eaten);
        if(c) 
            c->Carnivores::eat(*this);
    }
 }

Note that i had to make Base::eat public in order to call it from Derived.

mfontanini
  • 21,410
  • 4
  • 65
  • 73
  • I want to call the eat method of the to_be_eaten object. Not the "*this" object. – Chris Mar 22 '12 at 18:53
  • Just changed the "Animal" to "Base", sorry for the inconvenience. – Chris Mar 22 '12 at 18:56
  • @Chris Done, check that new solution. – mfontanini Mar 22 '12 at 18:59
  • @Chris Could you explain better what you're trying to do? As far as i understand it, `to_be_eaten.Base::eat(*this)` will fix your code. But i assume that you have tested it and it's not what you want. Can you give us a better description? – mfontanini Mar 22 '12 at 21:16
  • We have this inheritance: Animal(ABC) > Carnivores(ABC) > Wolf(Derived). I have implemented a method called eat in Carnivores class that will eat the to_be_eaten animal. Also, I have implemented a method of Wolf, eat, that will eat the animal (if the wolf can eat it, depending on its speed and several other conditions). There might be a chance that the wolf tries to eat another animal that is bigger that it, so the other animal will it the wolf. This is what I am trying to do. Call eat method of Carnivores, for the "victim" (in the case that the victim is becoming a hunter). – Chris Mar 22 '12 at 21:26
  • Then my solution should work; what i did was to call `Animal::eat` on to_be_eaten, that means, the body of `Animal::eat`, making the *this instance == to_be_eaten. Have you tried it? How is it not working? – mfontanini Mar 22 '12 at 22:33
  • We want to call Carnivores::eat on to_be_eaten (which is of type Animal). A casting might be needed to change the type of to_be_eaten, from Animal, to Carnivores – Chris Mar 23 '12 at 02:12
  • Have you tried my solution!?!?!? A cast will do nothing, it will always call the derived class' override. `to_be_eaten.Carnivores::eat(*this)` Try that and tell me if it works, i've answered this 7 hours ago and you haven't told me if it has worked or not. – mfontanini Mar 23 '12 at 02:39
  • Sorry fontanini, I tried it and got this: "error: ‘Carnivores’ is not a base of ‘Animal’"...We are passing as an argument a reference to Animal. – Chris Mar 24 '12 at 16:15
  • I editted my answer, you do require a dynamic_cast. However, the fact that you have to dynamic cast and explicitly call Carivores::eat, implies you have a bad design in your code. I would first check if there's a better design you can use. – mfontanini Mar 24 '12 at 17:27
  • Well, this was the design that we were asked to implement. What do you think would be a better one? other use of functions? – Chris Mar 24 '12 at 17:45
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/9260/discussion-between-fontanini-and-chris) – mfontanini Mar 24 '12 at 18:08
0

If I understand correctly, what you want is not to use a virtual call on the parameter object (to_be_eaten). I think only an object can do that for himself. I don't think there's a way for other objects to do it for him.

class Base
{
public:
  virtual eat(Base& to_be_eaten);
protected:
  virtual callEatNonVirtual(Base& other) = 0;
};

class Derived1 : public Base
{
public:
  virtual eat(Base& to_be_eaten)
  {
    to_be_eaten.callEatNonVirtual(*this);     
  }
protected:
  virtual callEatNonVirtual(Base& other)
  {
    Base::eat(other);
  } 
};

class Derived2 : public Base
{
public:
  virtual eat(Base& to_be_eaten)
  {
    to_be_eaten.callEatNonVirtual(*this);     
  }
protected:
  virtual callEatNonVirtual(Base& other)
  {
    Base::eat(other);
  } 
};
selalerer
  • 3,766
  • 2
  • 23
  • 33