21

I have this code:

#include <iostream>

class Base {
  public:
  virtual void sayHello() {
    std::cout << "Hello world, I am Base" << std::endl;
  }
};

class Derived: public Base {
  public:
  void sayHello() {
    std::cout << "Hello world, I am Derived" << std::endl;
  }
};

void testPointer(Base *obj) {
  obj->sayHello();
}

void testReference(Base &obj) {
  obj.sayHello();
}

void testObject(Base obj) {
  obj.sayHello();
}

int main() {
  {
    std::cout << "Testing with pointer argument: ";
    Derived *derived = new Derived;
    testPointer(derived);
  }
  {
    std::cout << "Testing with reference argument: ";
    Derived derived;
    testReference(derived);
  }
  {
    std::cout << "Testing with object argument: ";
    Derived derived;
    testObject(derived);
  }
}

The output is:

Testing with pointer argument: Hello world, I am Derived
Testing with reference argument: Hello world, I am Derived
Testing with object argument: Hello world, I am Base

My question is why both the pointer case void testPointer(Base *obj) and the reference case void testReference(Base &obj) return the result of derived instance of void sayHello() but not and the pass by copy case? What should I do to make the copy case to return the result of the derived class function void sayHello()?

Pekov
  • 527
  • 1
  • 9
  • 23
  • 1
    Your "Testing with reference argument" calls `testObject` instead of `testReference`. – Raymond Chen Dec 19 '17 at 15:46
  • 4
    Possible duplicate of [What is object slicing?](https://stackoverflow.com/questions/274626/what-is-object-slicing) – Raymond Chen Dec 19 '17 at 15:46
  • @RaymondChen Thanks for that, it shows the reference case is working as the pointer. But for pass by copy probably there is no way to call the derived class function implementation. – Pekov Dec 19 '17 at 16:38
  • 1
    Imagine the havoc if there were a way to call the derived class function on an object that isn't even an instance of the derived class. (The inbound parameter is a copy of the `Base` portion, not a full `Derived`.) – Raymond Chen Dec 19 '17 at 16:48

1 Answers1

24

A function taking a reference or pointer refers to the original object passed in, while by-value arguments will create a copy of your object. Since you are only copying the base part (since it takes a base object), you end up working with a copy of just the base part, and it acts like a base because it is a base.

This "base-only" copying is called "slicing" because it only copies part of your object, "slicing off" the derived part.

Chris Uzdavinis
  • 6,022
  • 9
  • 16