0

Let's say that I have class named MasterClass that has some children like ChildA, ChildB etc with public inheritance.

Also MasterClass has a var called MVar that is from type AnimalClass and obviously there are some children like DogClass, CatClass etc

MasterClass has that AnimalClass but ChildA has DogClass, ChildB has CatClass etc.

How I can make a function that is defined only in master but uses the inherit one throught its child I mean:

ChildA ca; ca.emitSound();

and emitSound just calls something like MVar.makeSound();

Where emitSound is only defined on AnimalClass and its behaviour depends on child's type.

My problem is that it seems that emitSound is always calling AnimalClass emitSound not DogClass emitSound.

Obviously if I define a emitSound in ChildA, ChildB etc it works fine but I just wanna make the code smaller.

Of course my real life issue is more complex that this stupid example but I think that the problem is pretty much the same, ie. emitSound could be a virtual one to allow some children to overwrite its behaviour etc.

Regards!

CODE:

AnimalClass 
{
public:
      AnimalClass();
      virtual void makeSound(){ printf("nosound";}        
}


DogClass: public AnimalClass 
{
public:
      DogClass();
      void makeSound(){ printf("bufff";}        
}


MasterClass 
{
public:
      MasterClass();
      AnimalClass *ani;
      void emitSound(){ani->makeSound();}     
}

ChildAClass: public MasterClass
{           
public:
      ChildAClass(){ani=new DogClass();}
      DogClass *ani;
}

main()
{
    ChildAClass c;
    c.emitSound();
}

The problem is that it prints "nosound" instead "bufff"

6
  • 1
    writing this relationship in code could make understanding simplier Commented Sep 13, 2015 at 15:47
  • you are right! done. Commented Sep 13, 2015 at 16:01
  • 1
    Could you write out a working example with a link to ideone.com perhaps? Commented Sep 13, 2015 at 16:04
  • I've just edited the question with an example Commented Sep 13, 2015 at 16:05
  • 1
    No, you didn't. An example which is guaranteed not to compile is not really an example. Commented Sep 13, 2015 at 16:07

3 Answers 3

1

The code you have provided does not compile so it is hard to know exactly what you are doing wrong in your real code. But it looks like you have an ani pointer in your derived class shadowing your ani pointer in your base class so the pointer in the base class is never initialized.

You need to ensure that the constructor of the derived class somehow initializes the pointer in the base class. For example the ChildAClass could have an instance of a DogClass and pass a reference to MasterClass constructor.

#include <cstdio>

class AnimalClass 
{
public:
    virtual void makeSound(){ printf("nosound");}        
};

class DogClass: public AnimalClass 
{
public:
    void makeSound() override { printf("bufff");}        
};

class MasterClass 
{
    AnimalClass *ani;
public:
    MasterClass(AnimalClass& animal) : ani(&animal) {}
    void emitSound(){ani->makeSound();}     
};

class ChildAClass: public MasterClass
{      
    DogClass dog;
public:
    ChildAClass() : MasterClass(dog){}
};

int main()
{
    ChildAClass c;
    c.emitSound();
}

Live demo.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you my code was not a working one it was just a fast stupid approach to expose the problem.
@FrankEscobar Well, we still don't really know for sure what your real problem is.
I wrote an explanation... This is a possible solution.
@luk32 You are probably right, but you are speculating a little on what OPs code really looks like.
No I don't, at least I believe so. His example isn't complete in the syntax sense. I don't think there is anything to interpret in the semantic sense. I.e. you can throw in missing includes and parentheses and it will work. I don't think you need any logic. The expected behaviour is also pretty clear. But I haven't done it =D. I did same assumption as you most probably. You wrote a possible solution, I wrote an explanation to the original behaviour.
0

The thing that happens is that AnimalClass::makeSound is called. This is because in child class you have two members ani in ChildAClass i.e.: ChildAClass::ani, and MasterClass::ani. The first one shadows the latter, but it still is there.

Now, even though you call emitSound through ChildAClass what is called is MasterClass::emitSound. So you need to look at things from this perspective. And from there you are calling makeSound from AnimalClass pointer not the DogClass, because AnimalClass::makeSound does not know anything about the derived class. In other words, members do not get "virtualized".

What you should have done is to have one member ani of type AnimalType* (or a reference) in the base class and initialize it properly in the derived class.

Comments

0
#include <iostream>

class Animal
{
public:
    virtual void sound()
    {
        std::cout << "Animal sound" << std::endl;
    }
    virtual ~Animal(){}
};
class Dog : public Animal
{
    void sound() //override
    {
        std::cout << "Dog sound" << std::endl;
    }
};

class Master
{
private:
    Animal *animal;
public:
    Master(Animal *a)
    {
        animal = a;
    }
    void emitSound()
    {
        animal->sound();
    }
    ~Master()
    {
        delete animal;
    }
};
class A : public Master
{
public:
    A(Dog *d) : Master(d){}
};

int main()
{
    A a(new Dog());
    a.emitSound();

    return 0;
}
OUTPUT: Dog sound

1 Comment

It could has sense but since I wanna to do it in a large amount of classes and they will be used by third party developers an ideal solution should be that A class could generate the Dog one without making it in a explicit way.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.