FAQ 24.10 Can an ABC s assignment operator be virtual ?

FAQ 24.10 Can an ABC's assignment operator be virtual?

An ABC's assignment operator can be virtual only if all derived classes of the ABC will be assignment compatible with all other derived classes and if the developer is willing to put up with a bit of extra work. This doesn't happen that often, but here's how to do it.

Classes derived from a base class are assignment compatible if and only if there's an isomorphism between the abstract states of the classes. For example, the abstract class Stack has concrete derived classes StackBasedOnList and StackBasedOnArray. These concrete derived classes have the same abstract state space as well as the same set of services and the same semantics. Thus, any Stack object can, in principle, be assigned to any other Stack object, whether or not they are instances of the same concrete class.

If all classes derived from an ABC are assignment compatible with all other derived classes from that ABC, there are two choices: when a user has a reference to the ABC, either prevent assignment or make it work correctly.

It is easiest on the class implementer to prevent assignment when the user has a reference to the base class. This is done by making the base class's assignment operator protected:. The disadvantage of this approach is that it restricts users from assigning arbitrary pairs of objects referred to by Stack references (that is, by Stack&).

The other choice is to make assignment work correctly when the user has a reference to the base class. This is done by making the base class's assignment operator public: and virtual. This approach allows any arbitrary Stack& to be assigned with any other Stack&, even if the two Stack objects are of different derived classes. The base class version of the assignment operator must be overridden in each derived class, and these overrides should copy the entire abstract state of the other Stack into the this object.

 class Stack { public:   virtual ~Stack()                    throw();   virtual void   push(int elem)       throw() = 0;   virtual int    pop()                throw() = 0;   virtual int    getElem(int n) const throw() = 0;   virtual Stack& operator= (const Stack& s) throw(); protected:   int n_; }; Stack::~Stack() throw() { } Stack& Stack::operator= (const Stack& s) throw() { n_ = s.n_; return *this; } void userCode(Stack& s, Stack& s2) { s = s2; } 

The overridden assignment operator and the overloaded assignment operator in a derived class, such as the StackArray class that follows, are often different.

 class StackArray : public Stack { public:   StackArray()                       throw();   virtual void push(int x)           throw();   virtual int  pop()                 throw();   virtual int  getElem(int n) const  throw();   virtual StackArray& operator= (const Stack& s) throw();                                                 //override   StackArray& operator= (const StackArray& s)    throw();                                                 //overload protected:   int data_[10]; }; StackArray::StackArray()             throw() : Stack() { } void StackArray::push(int x)         throw() { data_[n_++] = x; } int StackArray::pop()                throw() { return data_[--n_]; } int StackArray::getElem(int n) const throw() { return data_[n]; } // Override: StackArray& StackArray::operator= (const Stack& s) throw() {   Stack::operator= (s);   for (int i = 0; i < n_; ++i)     data_[i] = s.getElem(i);   return *this; } // Overload: StackArray& StackArray::operator= (const StackArray& s) throw() {   Stack::operator= (s);   for (int i = 0; i < n_; ++i)     data_[i] = s.data_[i];   return *this; } int main() {   StackArray s, s2;   userCode(s, s2); } 

Note that the override (StackArray::operator= (const Stack&)) returns a StackArray& rather than a mere Stack&. This is called a covariant return type.



C++ FAQs
C Programming FAQs: Frequently Asked Questions
ISBN: 0201845199
EAN: 2147483647
Year: 2005
Pages: 566
Authors: Steve Summit

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net