#Polymorphism with pointers and references

18 messages · Page 1 of 1 (latest)

olive dirge
#

I’m a complete noob with OOP and from what I understand, polymorphism allows child classes to have their own versions of the parent class’ methods by overwriting it. So if I have a parent class Animal with 2 child classes Dog and Cat, each of them can have their own implantation. But recently I’ve seen something about using pointers and references for polymorphism? This seems super confusing to me as I’ve just been doing Dog a1; or Cat a2; and it works fine but I’m not sure what difference the pointers and references do for polymorphism morphism?

shrewd pendantBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

modern vortex
#

Ofc it works if you create objects with the child classes. If you make an object with the parent class and want to call the methods in the child class how would you do that?

#

Would be nice to see the full code you’re working with, so we don’t have to make lots of assumptions

half zephyr
#

If you have Dog a1, that's always a Dog. If you have Animal a2, that's always just an animal, not a Dog or Cat (and this probably doesn't even make sense).
But sometimes you want to write code where it's decided at runtime whether an animal is a Cat or a Dog. Then you need to use a pointer or reference to an Animal that might point to a Cat or a Dog at runtime. For this to work as you'd expect, you need to make the member functions you're calling on the Animal virtual:

#include <string>
#include <iostream>

class Animal {
public:
    virtual ~Animal() = default;
    virtual std::string speak() const = 0;
};

class Cat: public Animal {
public:
    std::string speak() const override {
        return "meow";
    }
};

class Dog: public Animal {
public:
    std::string speak() const override {
        return "woof";
    }
};

void foo(const Animal& animal) {
    std::cout << animal.speak() << "\n";
}

int main() {
    foo(Cat{});
    foo(Dog{});
}

Here, you have only one functionfoo that can be called with any class that inherits from Animal

glass tigerBOT
#
Program Output
meow
woof
half zephyr
#

You should probably read the relevant parts of a tutorial

#

because there are a lot of details, and if I try to explain them again I'm probably just doing a worse job than a tutorial would

olive dirge
#

I think I understand now for sure

#

Would my understanding of poly morphism be right? The child classes can have their own version of functions? When I was doing some google searches I found that it said poly morphism was more of creating a base class and using that base class to Hold child classes with their own functions.
Ie. animal* a1 = new dog();
a1->speak();

Vs

dog a1;
a1.speak();

#

Apparently the latter isn’t like polymorphism? So I’m confused if that’s right

half zephyr
#

In programming, "polymorphism" generally means the idea that a value have one of several types.
In OOP, polymorphism generally means that this type is decided at runtime.
Like I said initially, if you write Dog a1; you simply have a Dog.
But if you have a function that takes an Animal& or Animal*, this can refer to a Dog or a Cat at runtime, so this is an example of polymorphism.
In the example I gave above, foo() can work with Cats and Dogs (and other types that inherit from Animal)

#

Tbh I don't really love this Animal example, because imo it's not clear from it why you'd want that

half zephyr
#

So let's make a slightly more realistic example:
Let's say you want to write a CPU raytracer, which you use to render a scene.
This scene consists of many different objects, and each object has surface that determines how it reflects light: There could be a diffuse surface, a reflective surface (like a mirror), a metallic surface, a surface that just absorbs all light, and so on.
So you could make each object hold a std::unique_ptr<Surface> surface as member variable , and then depending on what surface this object has (which is set at runtime, when loading the object) that would point to a MetallicSurface, a ReflectiveSurface, etc.
And if you want to know how a ray of light is reflected, you simply call surface->reflect(ray) and what the surface is pointing to decides how it reflects the ray of light.

#

An alternative design would be to simply write an enum of all the surfaces, and implement reflect() as a big switch over those enum values

#

Maybe a bit to advanced, so feel free to ignore the following:
Which design is better depends a lot on the circumstances:
With the enum design it's easy to add new functions that do stuff with surfaces, but if you want to add another surface you have to modify all of these functions.
With the inheritance based design it's easy to add a new derived surface classes, but if you want to add another function that does something different for each surface you have to add that to all these surface classes