Professional C__ - Marc Gregoire [148]
Note that the run-time type information is stored in the vtable of the object. Therefore, in order to use dynamic_cast, your classes must have at least one virtual method. If your classes don’t have a vtable, trying to use dynamic_cast will result in a compiler error which can be a bit obscure. Microsoft VC++ for example will give the error
error C2683: 'dynamic_cast' : 'MyClass' is not a polymorphic type.
Here are some examples:
class Base
{
public:
Base() {};
virtual ~Base() {}
};
class Derived : public Base
{
public:
Derived() {}
virtual ~Derived() {}
};
Code snippet from Casts\DynamicCast.cpp
The following example shows a correct usage of dynamic_cast.
Base* b;
Derived* d = new Derived();
b = d;
d = dynamic_cast Code snippet from Casts\DynamicCast.cpp The following dynamic_cast on a reference will cause an exception to be thrown. Chapter 10 covers the details of exception handling. Base base; Derived derived; Base& br = base; try { Derived& dr = dynamic_cast } catch (const bad_cast&) { cout << "Bad cast!\n"; } Code snippet from Casts\DynamicCast.cpp Note that you can perform the same casts down the inheritance hierarchy with a static_cast or reinterpret_cast. The difference with dynamic_cast is that it performs run-time (dynamic) type checking, while static_cast and reinterpret_cast will perform the casting even if they are erroneous. Summary of Casts The following table summarizes the casts you should use for difference situations. SITUATION CAST Remove const-ness const_cast Explicit cast supported by language (e.g., int to double, int to bool) static_cast Explicit cast supported by user-defined constructors or conversions static_cast Object of one class to object of another (unrelated) class Can’t be done Pointer-to-object of one class to pointer-to-object of another class in the same inheritance hierarchy static_cast or dynamic_cast Reference-to-object of one class to reference- to-object of another class in the same inheritance hierarchy static_cast or dynamic_cast Pointer-to-type to unrelated pointer-to-type reinterpret_cast Reference-to-type to unrelated reference-to-type reinterpret_cast Pointer-to-function to pointer-to-function reinterpret_cast SCOPE RESOLUTION Sometimes names in scopes hide identical names in other scopes. Other times, the scope you want is not part of the default scope resolution from that particular line in the program. If you don’t want the default scope resolution for a name, you can qualify the name with a specific scope using the scope resolution operator ::. For example, to access a static method of a class, one way is to prefix the method name with the name of the class (its scope) and the scope resolution operator. A second way is to access the static method through an object of that class. The following example demonstrates these options. The example defines a class Demo with a static get() method, a get() function that is globally scoped, and a get() function that is in the NS namespace. class Demo { public: static int get() { return 5; } }; int get() { return 10; } namespace NS { int get() { return 20; } }; Code snippet from Scope\Scope.cpp The global scope is unnamed, but you can access it specifically by using the scope resolution operator by itself (with no name prefix). The different get() functions can be called as follows. Demo* pd = new
As a C++ programmer, you need to familiarize yourself with the concept of scope. Every name in your program, including variable, function, and class names, is in a certain scope. You create scopes with namespaces, function definitions, and class definitions. When you try to access a variable, function, or class, the name is first looked up in the nearest enclosing scope, then the next scope, and so forth, up to the global scope. Any name not in a namespace, function, or class is assumed to be in the global scope. If it is not found in the global scope, at that point the compiler generates an undefined symbol error.