0

I wish to understand why a pointer to the "Derived" class object has to be used as an argument of the "PrintName" function in order to override the virtual "GetName" function. Why can a stack-allocated class object not be passed instead?

Why can't I do this:

class Base
{
public:

    virtual std::string GetName()
    {
        return "Base";
    }
};

class Derived: public Base
{
public:

    std::string GetName() override
    {
        return "Derived";
    }

};

void PrintName(Base obj)
{
    std::cout << obj.GetName() << std::endl;
}

int main()
{
    Base b;
    PrintName(b);

    Derived d ;
    PrintName(d);

    std::cin.get();
    
    return 0;
}

But have to do this:

...

void PrintName(Base* obj)
{
    std::cout << obj->GetName() << std::endl;
}

int main()
{
    Base* b = new Base();
    PrintName(b);

    Derived* d = new Derived();
    PrintName(d);

    std::cin.get();
    
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Hasnat123
  • 45
  • 7
  • 1
    `void PrintName(Base obj)` takes a base object. If you try to pass a derived to it, the derived bits get sliced off to make a base object to pass to the function. in `void PrintName(Base* obj)` you could pass a pointer to a stack allocated object and it would work. This isn't about how the object is allocated. You could also pass a reference to the object. What doesn't work is passing a coy of the base portion of the object. – Avi Berger Sep 30 '22 at 02:10
  • try to define `void PrintName(Base& obj)` – Iłya Bursov Sep 30 '22 at 02:14
  • 1
    Because that's the way the language is specified. `PrintName(b)` constructs a temporary instance of `Base` that is a *copy* of `b`, and strips out anything that is not part of `Base` (i.e. only a copy of the `Base` part is passed). This is described as object slicing. Passing a pointer (or a reference) allows the function to access information about `b`s *actual* type (i.e. that it is a `Derived`) - which, among other things, mean it can resolve a call of the virtual function i.e it calls `Derived::GetName()`. – Peter Sep 30 '22 at 02:23
  • 1
    Note that `PrintName` taking a pointer as an argument _does not_ prevent you from passing it a pointer to an object with automatic storage duration. Your calling code could equally well be `Base b; PrintName(&b); Derived d; PrintName(&d);`. As people have pointed out, you could also pass `obj` by reference. – Nathan Pierson Sep 30 '22 at 06:43

0 Answers0