I'm puzzled by A behavior in C++ overloading resolution. I have 2 classes, A and B, with A<:B. A has a virtual function f and B is supposed to override that function.
However, virtual functions don't seem to work as virtual when I invoke them using references. At first I thought this was due to the objects being allocated on the stack instead of the heap, but now I see that this weird behavior happens even when I use references to objects allocated on the heap.
What's the explanation for this?
#include<iostream>
using namespace std;
class A{
public:
virtual void foo(){ cout << "A::foo" << endl; }
};
class B : public A{
public:
virtual void foo(){ cout << "B::foo" << endl; }
};
void test_pt(A* pt){
cout << "test_pt " << (int)pt << " ";
pt->foo();
}
void test_ref(A ref){
cout << "test_ref " << (int)&ref << " ";
ref.foo();
}
int main(int argc, char* argv[]){
// pointers to objects allocated on heap
A* heap_pt_a = new A;
B* heap_pt_b = new B;
// virtual functions work as intended
test_pt(heap_pt_a); // test_pt 4975912 A::foo
test_pt(heap_pt_b); // test_pt 4975960 B::foo
// references to objects allocated on heap
A heap_ref_a = *heap_pt_a;
B heap_ref_b = *heap_pt_b;
// virtual functions work as non-virtual
test_ref(stack_ref_a); // test_ref 1571400 A::foo
test_ref(stack_ref_b); // test_ref 1571400 A::foo
// references to objects allocated on stack
A stack_ref_a;
B stack_ref_b;
// virtual functions work as non-virtual
test_ref(stack_ref_a); // test_ref 1571400 A::foo
test_ref(stack_ref_b); // test_ref 1571400 A::foo
// references to stack used as pointers to stack
// virtual functions work as intended
test_pt(&stack_ref_a); // test_pt 1571724 A::foo
test_pt(&stack_ref_b); // test_pt 1571712 B::foo
return 0;
}
The function test_ref
takes an A
by value. This is not passing by reference. The argument ref
in that function is a local object which was copied from an object in the calling function. (If it was copied from a B
this is called slicing).
Passing by reference would be:
void test_ref(A &ref)
Whether the objects are "stack" or "heap" makes no difference.
Similarly, your comment is wrong in:
// references to objects allocated on stack
A heap_ref_a = *heap_pt_a;
Here, heap_ref_a
is a copy of the object pointed to by heap_pt_a
. It is not a reference, they are now two distinct objects. A reference would be:
A &heap_ref_a = *heap_pt_a;