Polymorphism and virtual Destructors

When operating on classes in inheritance hierarchies, we often maintain containers of base class pointers that hold addresses of derived objects.

Example 23.3 defines a Bank class that has a container of various kinds of Account.

Example 23.3. src/derivation/assigcopy/bank.h

#ifndef BANK_H
#define BANK_H
#include 
class Account;

class Bank {
 public:
 Bank& operator<< (Account* acct); <-- 1
 ~Bank();
 private:
 QList<Account*> m_Accounts;
};
#endif

(1)This is how we add object ptrs into m_Accounts.

Bank is able to perform uniform operations on its collected Accounts by calling virtual methods on each one.

Example 23.4. src/derivation/assigcopy/bank.cpp

[ . . . . ]

#include "bank.h"
#include "account.h"

Bank::~Bank() {
 foreach (Account* acct, m_Accounts) {
 delete acct;
 }
 m_Accounts.clear();
}

In Example 23.4, delete acct causes an indirect call to the destructor of Account, as well as the subsequent release of allocated memory. However, while every address in the list is an Account, some (perhaps all) might point to derived-class objects and therefore require derived-class destructor calls.

If the destructor is virtual, the compiler allows run-time binding on the destructor call, instead of simply calling Account::~Account() on each one.

Example 23.5. src/derivation/assigcopy/bank.cpp

[ . . . . ]

Bank& Bank::operator<< (Account* acct) {
 m_Accounts << acct;
 return *this;
}

int main(int argc, char* argv[]) {
 Bank b;
 Account* a1 = new Account(1, 423, "Gene Kelly");
 JointAccount *a2 = new JointAccount(2, 1541, "Fred Astaire",
 "Ginger Rodgers");
 b << a1;
 b << a2;
} <-- 1

(1)At this point, the bank and all the accounts are destroyed.

Without declaring ~Account() to be virtual in the base class, we would get an incorrect result from running Example 23.5.[1]

[1] Compilers report a missing virtual in the destructor as a warning, and the behavior is undefined, so you may not see the same thing on your system.

Closing Acct - sending e-mail to primary acctholder:Gene Kelly
Closing Acct - sending e-mail to primary acctholder:Fred Astaire


By making the destructor virtual, both types of Account will get destroyed properly and, in this example, both account holders of a joint account will get proper e-mail notifications when the Bank is destroyed.

Closing Acct - sending e-mail to primary acctholder:Gene Kelly
Closing Joint Acct - sending e-mail to joint acctholder:Ginger
Rodgers
Closing Acct - sending e-mail to primary acctholder:Fred Astaire


If you declare one or more virtual methods in a class, you should define a virtual destructor for that class, even if it has an empty body.




Part I: Introduction to C++ and Qt 4

C++ Introduction

Classes

Introduction to Qt

Lists

Functions

Inheritance and Polymorphism

Part II: Higher-Level Programming

Libraries

Introduction to Design Patterns

QObject

Generics and Containers

Qt GUI Widgets

Concurrency

Validation and Regular Expressions

Parsing XML

Meta Objects, Properties, and Reflective Programming

More Design Patterns

Models and Views

Qt SQL Classes

Part III: C++ Language Reference

Types and Expressions

Scope and Storage Class

Statements and Control Structures

Memory Access

Chapter Summary

Inheritance in Detail

Miscellaneous Topics

Part IV: Programming Assignments

MP3 Jukebox Assignments

Part V: Appendices

MP3 Jukebox Assignments

Bibliography

MP3 Jukebox Assignments



An Introduction to Design Patterns in C++ with Qt 4
An Introduction to Design Patterns in C++ with Qt 4
ISBN: 0131879057
EAN: 2147483647
Year: 2004
Pages: 268

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