#include <iostream>
#include <typeinfo> // Header for typeid operator
using namespace std;
// Base class
class MyBase {
public:
virtual void Print() {
cout << "Base class" << endl;
};
};
// Derived class
class MyDerived : public MyBase {
public:
void Print() {
cout << "Derived class" << endl;
};
};
int main()
{
// Using typeid on built-in types types for RTTI
cout << typeid(100).name() << endl;
cout << typeid(100.1).name() << endl;
// Using typeid on custom types for RTTI
MyBase* b1 = new MyBase();
MyBase* d1 = new MyDerived();
MyBase* ptr1;
ptr1 = d1;
cout << typeid(*b1).name() << endl;
cout << typeid(*d1).name() << endl;
cout << typeid(*ptr1).name() << endl;
if ( typeid(*ptr1) == typeid(MyDerived) ) {
cout << "Ptr has MyDerived object" << endl;
}
// Using dynamic_cast for RTTI
MyDerived* ptr2 = dynamic_cast<MyDerived*> ( d1 );
if ( ptr2 ) {
cout << "Ptr has MyDerived object" << endl;
}
}
OUTPUT:
i
d
6MyBase
9MyDerived
9MyDerived
Ptr has MyDerived object
Ptr has MyDerived object
Monday, December 6, 2010
RTTI examples
RTTI -Notes - dynamic_cast
Runtime Type Information (RTTI) is the concept of determining the type of any variable during execution (runtime.) The RTTI mechanism contains:
The first dynamic_cast statement will work because we cast from derived to base. The second dynamic_cast statement will produce a compilation error because base to derived conversion is not allowed with dynamic_cast unless the base class is polymorphic.
If a class is polymorphic then dynamic_cast will perform a special check during execution. This check ensures that the expression is a valid and complete object of the requested class.
Take a look at the example:
In the example we perform two dynamic_casts from pointer objects of type Base_Class* (namely ptr_a and ptr_b) to a pointer object of type Derived_Class*.
If everything goes well then the first one should be successful and the second one will fail. The pointers ptr_a and ptr_b are both of the type Base_Class. The pointer ptr_a points to an object of the type Derived_Class. The pointer ptr_b points to an object of the type Base_Class. So when the dynamic type cast is performed then ptr_a is pointing to a full object of class Derived_Class, but the pointer ptr_b points to an object of class Base_Class. This object is an incomplete object of class Derived_Class; thus this cast will fail!
Because this dynamic_cast fails a null pointer is returned to indicate a failure. When a reference type is converted with dynamic_cast and the conversion fails then there will be an exception thrown out instead of the null pointer. The exception will be of the type bad_cast.
With dynamic_cast it is also possible to cast null pointers even between the pointers of unrelated classes.
Dynamic_cast can cast pointers of any type to void pointer(void*).
- The operator dynamic_cast
- The operator typeid
- The struct type_info
Dynamic_cast
The dynamic_cast can only be used with pointers and references to objects. It makes sure that the result of the type conversion is valid and complete object of the requested class. This is way a dynamic_cast will always be successful if we use it to cast a class to one of its base classes. Take a look at the example:
class Base_Class { };
class Derived_Class: public Base_Class { };
Base_Class a; Base_Class * ptr_a;
Derived_Class b; Derived_Class * ptr_b;
ptr_a = dynamic_cast<Base_Class *>(&b);
ptr_b = dynamic_cast<Derived_Class *>(&a);
If a class is polymorphic then dynamic_cast will perform a special check during execution. This check ensures that the expression is a valid and complete object of the requested class.
Take a look at the example:
// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;
class Base_Class { virtual void dummy() {} };
class Derived_Class: public Base_Class { int a; };
int main () {
try {
Base_Class * ptr_a = new Derived_Class;
Base_Class * ptr_b = new Base_Class;
Derived_Class * ptr_c;
ptr_c = dynamic_cast< Derived_Class *>(ptr_a);
if (ptr_c ==0) cout << "Null pointer on first type-cast" << endl;
ptr_c = dynamic_cast< Derived_Class *>(ptr_b);
if (ptr_c ==0) cout << "Null pointer on second type-cast" << endl;
} catch (exception& my_ex) {cout << "Exception: " << my_ex.what();}
return 0;
}
If everything goes well then the first one should be successful and the second one will fail. The pointers ptr_a and ptr_b are both of the type Base_Class. The pointer ptr_a points to an object of the type Derived_Class. The pointer ptr_b points to an object of the type Base_Class. So when the dynamic type cast is performed then ptr_a is pointing to a full object of class Derived_Class, but the pointer ptr_b points to an object of class Base_Class. This object is an incomplete object of class Derived_Class; thus this cast will fail!
Because this dynamic_cast fails a null pointer is returned to indicate a failure. When a reference type is converted with dynamic_cast and the conversion fails then there will be an exception thrown out instead of the null pointer. The exception will be of the type bad_cast.
With dynamic_cast it is also possible to cast null pointers even between the pointers of unrelated classes.
Dynamic_cast can cast pointers of any type to void pointer(void*).
RTTI - Notes - typeid
type_id:
In C++, the typeid keyword is used to determine the class of an object at runtime.
In C++, the typeid keyword is used to determine the class of an object at runtime.
#include <iostream> #include <typeinfo> //for 'typeid' to work class Person { public: // ... Person members ... virtual ~Person() {} }; class Employee : public Person { // ... Employee members ... }; int main () { Person person; Employee employee; Person *ptr = &employee; // The string returned by typeid::name is implementation-defined std::cout << typeid(person).name() << std::endl; // Person (statically known at compile-time) std::cout << typeid(employee).name() << std::endl; // Employee (statically known at compile-time) std::cout << typeid(ptr).name() << std::endl; // Person * (statically known at compile-time) std::cout << typeid(*ptr).name() << std::endl; // Employee (looked up dynamically at run-time // because it is the dereference of a // pointer to a polymorphic class) }
Tuesday, November 30, 2010
OOPs - definitions
Encapsulation is binding of attributes and behaviors. Hiding the actual implementation and exposing the functionality of any object.
Hiding the complexity. It is a process of defining communication interface for the functionality and hiding rest of the things.
An abstract class is a special kind of class that cannot be instantiated. It normally contains one or more abstract methods or abstract properties. It provides body to a class.
What is Polymorphism? Mean by more than one form. Ability to provide different implementation based on different number/type of parameters.
Hiding the complexity. It is a process of defining communication interface for the functionality and hiding rest of the things.
An abstract class is a special kind of class that cannot be instantiated. It normally contains one or more abstract methods or abstract properties. It provides body to a class.
What is Polymorphism? Mean by more than one form. Ability to provide different implementation based on different number/type of parameters.
Sunday, November 21, 2010
Why destructor should be virtual?
In the following code if the destructor is not virtual then the destructor of dervied calls is not called and clean up could not be done for Derrived class hence result in memory leaks
Usually the destrcutor of child is called first then parents that order is not followed in the following code if virtual keyword is not used.
#include <iostream.h>
class Base
{
public:
Base(){ cout<<"Constructor: Base"<<endl;}
virtual ~Base(){ cout<<"Destructor : Base"<<endl;}
};
class Derived: public Base
{
//Doing a lot of jobs by extending the functionality
public:
Derived(){ cout<<"Constructor: Derived"<<endl;}
~Derived(){ cout<<"Destructor : Derived"<<endl;}
};
void main()
{
Base *Var = new Derived();
delete Var;
}
Usually the destrcutor of child is called first then parents that order is not followed in the following code if virtual keyword is not used.
#include <iostream.h>
class Base
{
public:
Base(){ cout<<"Constructor: Base"<<endl;}
virtual ~Base(){ cout<<"Destructor : Base"<<endl;}
};
class Derived: public Base
{
//Doing a lot of jobs by extending the functionality
public:
Derived(){ cout<<"Constructor: Derived"<<endl;}
~Derived(){ cout<<"Destructor : Derived"<<endl;}
};
void main()
{
Base *Var = new Derived();
delete Var;
}
Can we have virtual constructor?
No, I think this is syntax error
Constructor is responsible for creating the instance of the class it cannot delegate the responsibility to other class.
Constructor is responsible for creating the instance of the class it cannot delegate the responsibility to other class.
Wednesday, November 10, 2010
Famous - Abstract Class and Concrete Class
Abstract Class which does not provide implementation of all its member functions.
Subscribe to:
Posts (Atom)