#include <iostream>
#include <typeinfo>
#include <string>
#ifdef __GNUC__
#include <cxxabi.h>
template< typename T > std::string type_name( T& x )
{
enum { MAX_LEN = 2047, SIZE = MAX_LEN+1 } ;
char temp[SIZE] ;
std::size_t sz = SIZE ;
int status ;
__cxxabiv1::__cxa_demangle( typeid(x).name(), temp, &sz, &status ) ;
return status==0 ? temp : "__cxa_demangle error" ;
}
#else // not g++ compatible
template< typename T > std::string type_name( T& x )
{ returntypeid(x).name() ; }
#endif
struct base_class
{
virtual ~base_class() {}
void statically_bound() const
{
std::cout << "\nbase_class::statically_bound() ""is bound early (at compile-time)\n""it is dispached based on the compile-time type\n";
}
virtualvoid dynamically_bound() const
{
std::cout << "\nbase_class::dynamically_bound() ""is bound late (at run-time)\nwhen invoked ""through a pointer or a reference\n""(without explicit scope resolution)\n""it is dispached based on the run-time type of the object\n";
}
};
void test_it( const base_class* pointer )
{
staticint n = 0 ;
std::cout << "\ntest_it - call #" << ++n << "\n--------------------\n" ;
std::cout << "compile-time type of pointer is: " << type_name(pointer) << '\n'
<< "run-time type of pointed object is: " << type_name(*pointer) << '\n' ;
// this will always call base_class::statically_bound()
pointer->statically_bound() ;
// this will call ???::dynamically_bound()
// where ??? is the run-time type of the object
// each time a different implementation of the function may be called
pointer->dynamically_bound() ;
// this will always call base_class::dynamically_bound()
// the scope resolution operator is a compile-time operator
// (uncomment to see what happens)
// pointer->base_class::dynamically_bound() ;
std::cout << "\n====================================================\n" ;
}
struct derived_class : base_class
{
void statically_bound() const // hides base_class::statically_bound
{
std::cout << "\n*** derived_class::statically_bound()\n\t""hides base_class::statically_bound\n" ;
}
// comment out the override specifier for C++ of 1998 vintage
virtualvoid dynamically_bound() const override
{
std::cout << "\n*** derived_class::dynamically_bound()\n\t""overrides base_class::dynamically_bound\n" ;
}
};
int main()
{
base_class b ;
derived_class d ;
base_class* ptr = &b ;
test_it(ptr) ;
ptr = &d ;
test_it(ptr) ;
}
Output:
test_it - call #1
--------------------
compile-time type of pointer is: base_class const*
run-time type of pointed object is: base_class
base_class::statically_bound() is bound early (at compile-time)
it is dispached based on the compile-time type
base_class::dynamically_bound() is bound late (at run-time)
when invoked through a pointer or a reference
(without explicit scope resolution)
it is dispached based on the run-time type of the object
====================================================
test_it - call #2
--------------------
compile-time type of pointer is: base_class const*
run-time type of pointed object is: derived_class
base_class::statically_bound() is bound early (at compile-time)
it is dispached based on the compile-time type
*** derived_class::dynamically_bound()
overrides base_class::dynamically_bound
====================================================