Polymorphism
See also: Polymorphism in object-oriented programming
Polymorphism enables one common interface for many implementations, and for objects to act differently under different circumstances.
C++ supports several kinds of static (compile-time) and dynamic (run-time) polymorphism. Compile-time polymorphism does not allow for certain run-time decisions, while run-time polymorphism typically incurs a performance penalty.
Static polymorphism
Function overloading allows programs to declare multiple functions having the same name (but with different arguments). The functions are distinguished by the number and/or types of their formal parameters. Thus, the same function name can refer to different functions depending on the context in which it is used. The type returned by the function is not used to distinguish overloaded functions.
Similarly, operator overloading allows programs to define certain operators (such as +, !=, <, or &) to result in a function call that depends on the types of the operands they are used on. Overloading an operator does not change the precedence of calculations involving the operator, nor does it change the number of operands that the operator uses (any operand may however be ignored). The . :: .* ? operators can not be overloaded.
Default arguments are used when defining a different function is not needed when supplying a default value for an argument will suffice. Care should be taken when using default arguments in conjunction with overloaded functions to not cause a conflict over which function to use. For instance, the following code:
// function with default argument but also an overloaded function
int strcpy(char *str1, char *str2, short unsigned n=65535);
// second overloaded function
int strcpy(char *str1, char *str2);
will compile correctly when strcpy is used with an argument for n but not when no argument is specified. This is because the compiler has no means of knowing if the intended function is the first form with a default value of 65535 for n or the second form with no n argument.
Templates in C++ provide a sophisticated mechanism for writing generic, polymorphic code. In particular, through the Curiously Recurring Template Pattern it's possible to implement a form of static polymorphism that closely mimics the syntax for overriding virtual methods (a dynamic polymorphism technique described below). Since C++ templates are type-aware and Turing-complete they can also be used to let the compiler resolve recursive conditionals and generate substantial programs through template metaprogramming.
Dynamic polymorphism
Variable pointers (and references) of a base class type in C++ can refer to objects of any derived classes of that type in addition to objects exactly matching the variable type. This allows arrays and other kinds of containers to hold pointers to objects of differing types. Because assignment of values to variables usually occurs at run-time, this is necessarily a run-time phenomenon.
i have a que here...
can u give any example which emphazize use of using base class (pointer or reference) necessary to have containers holding different types?
......................................
C++ also provides a dynamic_cast operator, which allows the program to safely attempt conversion of an object into an object of a more specific object type (as opposed to conversion to a more general type, which is always allowed). This feature relies on run-time type information (RTTI). Objects known to be of a certain specific type can also be cast to that type with static_cast, a purely compile-time construct which is faster and does not require RTTI.
Through virtual member functions, different objects that share a common base class may all support an operation in different ways. The member functions implemented by the derived class are said to override the same member functions of the base class. In contrast with function overloading, the parameters for a given member function are always exactly the same in number and type. Only the type of the object for which this method is called varies. In addition to standard member functions, operator overloads and destructors can also be virtual.
By virtue of inherited objects being polymorphic, it may not be possible for the compiler to determine the type of the object at compile time. The decision is therefore put off until runtime, and is called dynamic dispatch. In this way, the most specific implementation of the function is called, according to the actual run-time type of the object. In C++, this is commonly done using virtual function tables. This may sometimes be bypassed by prepending a fully qualified class name before the function call, but calls to virtual functions are in general always resolved at run time.
An example:
#include <iostream>
class Bird // the "generic" base class
{
public:
virtual void OutputName() {std::cout << "a bird";}
virtual ~Bird() {}
};
class Swan : public Bird // Swan derives from Bird
{
public:
void OutputName() {std::cout << "a swan";} // overrides virtual function
};
int main()
{
Swan mySwan ; // Creates a swan.
Bird* myBird = &mySwan; // Declares a pointer to a generic Bird,
// and sets it pointing to a newly created Swan.
i donot understand what is the need of using base class pointer here to refer to derived class object.... why don't we directly use derived class pointer..like Swan * mynewSwan=&mySwan;
and then mynewSwan->OutputName();
can anyone educate me on this ???
myBird->OutputName(); // This will output "a swan", not "a bird".
return 0;
}
Guys let me know if I am wrong?