354
03.06.2005, 14:10 Uhr
Matthias Hofmann
Administrator Bürstenkaiser
Themenstarter Beiträge: 4133 Dabei seit: 15.04.2003, 23:00 Uhr |
Sicher sitzt Ihr jetzt alle daheim und fragt Euch, was zum Geier ich eigentlich gerade mache. Nun gut, da es Euch so brennend interessiert: ich wärme zum Frühstück mein Gehirn etwas auf indem ich nutzlosen, aber hammergeilen Quellcode schreibe!
Mit Klomanager II hat das aber nicht direkt etwas zu tun. Es geht vielmehr um das Entwicklen und Testen einer wiederverwendbaren Basisklasse, die abgeleiteten Objekten einen virtuellen Kopierkonstruktor zur Verfügung stellt. Diese Klasse namens Cloneable ist in der Datei commbase.hpp definiert:
format_source('/*--------------------------------------------------
File: commbase.hpp
Author: Matthias Hofmann
Provides common base classes.
----------------------------------------------------*/
#ifndef COMMBASE_HPP #define COMMBASE_HPP
#include <memory> #include <typeinfo> #include <stdexcept>
// Provides a virtual copy constructor. The template // argument must belong to the inheritance chain of // the class deriving from it. template <class T> class Cloneable { // An object's most derived class must implement // this function so that it allocates a copy of // itself and returns a pointer to it. virtual T* clone() const = 0;
public: // The non-virtual interface calling // the virtual copy constructor. std::auto_ptr<T> Clone() const { std::auto_ptr<T> temp( clone() ); // Throw an exception if the type of the copy // does not match. A null pointer will cause a // bad_typeid exception to be thrown. if ( typeid( *temp ) != typeid( *this ) ) throw std::logic_error( "type mismatch" );
return temp; } };
#endif // COMMBASE_HPP')Mit dieser Klasse kann man wie gesagt geradezu fantastische Sachen machen. Ein entsprechendes Treiberprogramm finden wir in der Datei main.cpp:
format_source('/*--------------------------------------------------
File: main.cpp
Author: Matthias Hofmann
Driver program for common base classes.
----------------------------------------------------*/
#include <iostream> #include <algorithm> #include <list> #include "commbase.hpp"
// Define an abstract cloneable object. class Object : public Cloneable<Object> { // An object's most derived class must implement // this function so that it identifies itself. virtual void whois() const = 0;
public: // The non-virtual interface calling // the virtual identification function. void Whois() const { whois(); } };
// Define a concrete cloneable object of type A. class A : public Object { // Implement the virtual copy constructor. // Note that VC++ 6.0 does not support // a return value of type pointer to A. virtual Object* clone() const { return new A( *this ); }
// Implement the virtual // identification function. virtual void whois() const { std::cout << "A" << std::endl; } };
// Define a concrete cloneable object of type B. class B : public Object { // Implement the virtual copy constructor. // Note that VC++ 6.0 does not support // a return value of type pointer to B. virtual Object* clone() const { return new B( *this ); }
// Implement the virtual // identification function. virtual void whois() const { std::cout << "B" << std::endl; } };
// An auxiliary type definition. typedef std::list<Object*> pobj_list;
// An auxiliary cloning function. Object* clone( const Object* p ) { return p->Clone().release(); }
// Creates a list of objects. pobj_list create_list() { pobj_list temp;
// Insert objects arbitrarily. temp.push_back( new A ); temp.push_back( new B ); temp.push_back( new B ); temp.push_back( new A );
return temp; }
// Removes each object in the passed // list while calling delete on it. void clear_list( pobj_list& l ) { while ( !l.empty() ) { // Obtain object. Object* p = l.back();
// Remove object. l.pop_back();
// Delete object. delete p; } }
// Creates a list of clones of the // objects in the passed list. pobj_list clone_list( const pobj_list& l ) { pobj_list temp;
try { // Insert a clone of each object in the // source list into the destination list. std::transform( l.begin(), l.end(), back_inserter( temp ), clone ); } catch ( ... ) { // Clean up and rethrow. clear_list( temp ); throw; }
return temp; }
int main() { // Create a list of objects. pobj_list l1 = create_list();
std::cout << "List of original objects:" << std::endl;
// Make each object identify itself. std::for_each( l1.begin(), l1.end(), std::mem_fun( Object::Whois ) );
try { // Clone the list of objects. pobj_list l2 = clone_list( l1 );
std::cout << "\nList of cloned objects:" << std::endl;
// Make each object identify itself. std::for_each( l2.begin(), l2.end(), std::mem_fun( Object::Whois ) );
// Clear the cloned list. clear_list( l2 ); } catch ( std::exception& ex ) { // Handle an exception. std::cout << std::endl << ex.what() << std::endl; }
// Clear the original list. clear_list( l1 );
std::cout << std::endl;
return 0; }')Man beachte, da� der Quelltext unter Visual C++ 6.0 leider nicht kompilierbar ist. Mit standardkonformen Kompilern dürfte dies allerdings kein Problem sein.
So, und jetzt ist es langsam Zeit für's Mittagessen! ----- Matthias Hofmann | Klomanager Deluxe jetzt bei Gamesload kaufen |