#include <iostream>
using namespace std;

class SuperClass {
public:
	virtual void print(int line) {
		cout << "line " << line << ": SuperClass" << endl;
	}
};

class DerivedClass : public SuperClass {
public:
	virtual void print(int line) {
		cout << "line " << line << ": DerivedClass" << endl;
	}
};

void PrintByPointer (int line, SuperClass *foo)
{
	foo->print(line);
}

void PrintByReference (int line, SuperClass &foo)
{
	foo.print(line);
}

void PrintByValue (int line, SuperClass foo)
{
	foo.print(line);
}

int main ()
{
	SuperClass		stack_super;
	DerivedClass	stack_derived;
	SuperClass*		heap_super	 = new SuperClass();
	DerivedClass*	heap_derived = new DerivedClass();
	SuperClass*		mixed_pointer = heap_derived;

	cout << "Direct invocations" << endl;
	stack_super.print(__LINE__);
	stack_derived.print(__LINE__);
	heap_super->print(__LINE__);
	heap_derived->print(__LINE__);
	mixed_pointer->print(__LINE__);

	cout << endl << "Passed by pointer" << endl;
	PrintByPointer(__LINE__, &stack_super);
	PrintByPointer(__LINE__, &stack_derived);
	PrintByPointer(__LINE__, heap_super);
	PrintByPointer(__LINE__, heap_derived);
	PrintByPointer(__LINE__, mixed_pointer);

	cout << endl << "Passed by reference" << endl;
	PrintByReference(__LINE__, stack_super);
	PrintByReference(__LINE__, stack_derived);
	PrintByReference(__LINE__, *heap_super);
	PrintByReference(__LINE__, *heap_derived);
	PrintByReference(__LINE__, *mixed_pointer);

	cout << endl << "Passed by value" << endl;
	PrintByValue(__LINE__, stack_super);
	PrintByValue(__LINE__, stack_derived);
	PrintByValue(__LINE__, *heap_super);
	PrintByValue(__LINE__, *heap_derived);
	PrintByValue(__LINE__, *mixed_pointer);
}

/* Output:

Direct invocations
line 42: SuperClass
line 43: DerivedClass
line 44: SuperClass
line 45: DerivedClass
line 46: DerivedClass

Passed by pointer
line 49: SuperClass
line 50: DerivedClass
line 51: SuperClass
line 52: DerivedClass
line 53: DerivedClass

Passed by reference
line 56: SuperClass
line 57: DerivedClass
line 58: SuperClass
line 59: DerivedClass
line 60: DerivedClass

Passed by value
line 63: SuperClass
line 64: SuperClass
line 65: SuperClass
line 66: SuperClass
line 67: SuperClass

*/

