Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why its dangerous to use pass by value when function parameter expects an Abstract class object?

Tags:

c++

I read below statements in Addison Wesley FAQs.

Beware: passing objects by value can be dangerous in some situations. Often it is better to pass objects by reference-to-const than to pass them by value. For example, pass-by-value won't work if the destination type is an abstract base class and can result in erroneous behavior at runtime if the parameter's class has derived classes. However if the class of the parameter is guaranteed not to have derived classes, and if the function being called needs a local copy to work with, pass-by-value can be useful.

How it can be erroneous behavior at runtime if destination type is an Abstract class and if the parameter's class has derived class ? Does copy constructor solve this problem ? If so, how ? Thank you.

EDIT: So, should the statement above be "erroneous behavior at compile time" ? Not "runtime" .

like image 200
bjskishore123 Avatar asked Dec 10 '25 22:12

bjskishore123


1 Answers

There are two things here, and you seem to be mixing them up:

1) If the destination type is an abstract class and you pass by value, there will be no runtime error: it won't compile, period.

2) When there will be a runtime error is if the destination type is concrete but has derived classes. Consider this example:

#include <iostream>

struct A {
    virtual void f() { std::cout << "A\n"; }
};
struct B : public A {
    virtual void f() { std::cout << "B\n"; }
};

void func(A a){
    a.f();
}

int main() {
    func( B() );
}

It compiles fine, but outputs A. If you change the parameter to A&, polymorphism works as expected and B is printed. This problem is known as slicing, and there's a nice question here on SO about it.

As a general rule of thumb, if the class has any virtual functions you should a) declare the destructor as virtual and b) avoid passing it by value.

I actually avoid passing any parameter by value, unless I'm sure it's a primitive type such as an int. If you're writing a template, you're better off accepting all parameters as const T&.

like image 123
Pedro d'Aquino Avatar answered Dec 12 '25 12:12

Pedro d'Aquino



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!