1

For instance, consider:

class Deriv : public Base {...};
...
bar(Deriv d);
bar(Base b);
foo(Base b) {bar(b);}
...
Deriv x;
foo(x); // does x get treated as Base for the bar() call
        // or retain its Deriv type?

And also what if foo passes by reference?

mchen
  • 9,808
  • 17
  • 72
  • 125

2 Answers2

6

You're passing by value, hence you're creating a new object of type Base and doing a copy assign to it..

Very bad, you'll experience slicing..it will not retain it's stage an not suggested. http://en.wikipedia.org/wiki/Object_slicing

Either pass by reference or const reference which is anyhow better and quicker:

bar(const Base& b)

or pass a pointer to the object and you'll retain the state. bar(Base* b);

That would be the correct way to handle this.

Dory Zidon
  • 10,497
  • 2
  • 25
  • 39
3

In your example, x will be a Base, this is because you are creating a new Base object when you call the function. That is, on the function call, the constructor for Base is called, creating a Base b copied from the argument's (x's) Base subobject (known as object slicing). It's not being treated as a Base, it creates a new Base

If you, however, take the argument as a Base &, it will be treated as a Derived, consider the following code:

#include <iostream>
class Base {
    public:
        virtual void func() const {
            std::cout << "Base::Func()" << std::endl;
        }

};

class Derived : public Base {
    public:
        virtual void func() const {
            std::cout << "Derived::Func()" << std::endl;
        }
};

int do_func_value(Base b){
    b.func(); // will call Base::func
}

int do_func_ref(const Base & b){
    b.func(); // will call whatever b's actual type is ::func
}

int main(void){
    Derived d;
    do_func_value(d);
    do_func_ref(d);
    return 0;
}

this outputs:

Base::Func()
Derived::Func()
Ryan Haining
  • 35,360
  • 15
  • 114
  • 174