Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 88 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
88
Dung lượng
304,21 KB
Nội dung
Not only does this save code space, it allows easy propagation of changes Pure virtual definitions It’s possible to provide a definition for a pure virtual function in the base class You’re still telling the compiler not to allow objects of that abstract base class, and the pure virtual functions must still be defined in derived classes in order to create objects However, there may be a common piece of code that you want some or all of the derived class definitions to call rather than duplicating that code in every function Here’s what a pure virtual definition looks like: //: C15:PureVirtualDefinitions.cpp // Pure virtual base definitions #include using namespace std; class Pet { public: virtual void speak() const = 0; virtual void eat() const = 0; // Inline pure virtual definitions illegal: //! virtual void sleep() const = {} }; // OK, not defined inline void Pet::eat() const { cout () const { require(ps.storage[index] != 0, "PStash::iterator::operator->returns 0"); return current(); } // Remove the current element: T* remove(){ return ps.remove(index); } // Comparison tests for end: bool operator==(const iterator& rv) const { return index == rv.index; } bool operator!=(const iterator& rv) const { return index != rv.index; } }; iterator begin() { return iterator(*this); } iterator end() { return iterator(*this, true);} }; // Destruction of contained objects: template PStash::~PStash() { for(int i = 0; i < next; i++) { delete storage[i]; // Null pointers OK storage[i] = 0; // Just to be safe } delete []storage; } template int PStash::add(T* element) { if(next >= quantity) inflate(); storage[next++] = element; return(next - 1); // Index number } template inline T* PStash::operator[](int index) const { require(index >= 0, "PStash::operator[] index negative"); if(index >= next) 770 Thinking in C++ www.BruceEckel.com return 0; // To indicate the end require(storage[index] != 0, "PStash::operator[] returned null pointer"); return storage[index]; } template T* PStash::remove(int index) { // operator[] performs validity checks: T* v = operator[](index); // "Remove" the pointer: storage[index] = 0; return v; } template void PStash::inflate(int increase) { const int tsz = sizeof(T*); T** st = new T*[quantity + increase]; memset(st, 0, (quantity + increase) * tsz); memcpy(st, storage, quantity * tsz); quantity += increase; delete []storage; // Old storage storage = st; // Point to new memory } #endif // TPSTASH2_H ///:~ Most of this file is a fairly straightforward translation of both the previous PStash and the nested iterator into a template This time, however, the operators return references to the current iterator, which is the more typical and flexible approach to take The destructor calls delete for all contained pointers, and because the type is captured by the template, proper destruction will take place You should be aware that if the container holds pointers to a base-class type, that type should have a virtual destructor to ensure proper cleanup of derived objects whose addresses have been upcast when placing them in the container The PStash::iteratorfollows the iterator model of bonding to a single container object for its lifetime In addition, the copyconstructor allows you to make a new iterator pointing at the same 16: Introduction to Templates 771 ... abstract data typing, inheritance, and polymorphism 716 Thinking in C+ + www.BruceEckel.com Exercises Solutions to selected exercises can be found in the electronic document The Thinking in C+ +... results Thinking in C+ + www.BruceEckel.com 16 17 18 19 20 21 22 Modify VirtualsInDestructors.cpp inheriting a class by from Derived and overriding f( ) and the destructor In main( ), create and upcast... fibonacci #include "fibonacci.h" #include " /require.h" #include using namespace std; class IntStack { enum { ssize = 10 0 }; int stack[ssize]; int top; 724 Thinking in C+ + www.BruceEckel.com