diff --git a/.gitignore b/.gitignore index 2ac684a..07ad1ce 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ casts classes lvalues bad_alloc +rtti diff --git a/CMakeLists.txt b/CMakeLists.txt index d3e8f8d..7a66a9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,3 +17,4 @@ add_executable(casts casts.cpp) add_executable(classes classes.cpp) add_executable(lvalues lvalues.cpp) add_executable(bad_alloc bad_alloc.cpp) +add_executable(rtti rtti.cpp) diff --git a/rtti.cpp b/rtti.cpp new file mode 100644 index 0000000..ad0d2d8 --- /dev/null +++ b/rtti.cpp @@ -0,0 +1,79 @@ +#include +#include +#include + + +class Nail { + public: + Nail(float length) + : length(length) {}; + + float getLength() { + return length; + } + + private: + float length; +}; + + +class Tool { + public: + virtual void use() { + std::cout << "Just using some tool." << std::endl; + } +}; + + +class Hammer : public Tool { + public: + virtual void use() { + std::cout << "Hammer time!" << std::endl; + } + + void use(Nail nail) { + std::cout << "The nail is " << nail.getLength() << " cm long" << std::endl; + } +}; + + +class SledgeHammer : public Hammer { + public: + void use(Nail nail __attribute__((unused))) { + throw std::runtime_error("Can't use a sledge hammer on nails!"); + } +}; + + +void useSomeTool(Tool &tool) { + // RTTI gives up the type of the derived class. + std::cout << "Look, it's a " << typeid(tool).name() << "!" << std::endl; + + // XXX What about subclasses of Hammer? + if(typeid(tool) == typeid(Hammer)) { + std::cout << "Stop! "; + } + tool.use(); + + // Or dynamic_cast it and use it on a nail + // XXX How to use a reference here? + Hammer* h = dynamic_cast(&tool); + if (h) { + Nail nail(10); + h->use(nail); + } +} + + +int main() { + Tool tool; + Hammer hammer; + SledgeHammer sledgehammer; + + useSomeTool(tool); + useSomeTool(hammer); + useSomeTool(sledgehammer); +} + +// XXX http://en.cppreference.com/w/cpp/language/typeid +// XXX https://en.wikipedia.org/wiki/Dynamic_cast