But using function notation instead of operator notation lets you use the scope-resolution operator. In effect, the statement means the following:

*this = hs;  // use baseDMA::operator=()

But, of course, the compiler ignores comments, so if you used the latter code, the compiler would use hasDMA::operator=() instead and create a recursive call. Using function notation gets the correct assignment operator called.

In summary, when both the base class and the derived class use dynamic memory allocation, the derived-class destructor, copy constructor, and assignment operator all must use their base-class counterparts to handle the base-class component. This common requirement is accomplished three different ways. For a destructor, it is done automatically. For a constructor, it is accomplished by invoking the base-class copy constructor in the member initialization list, or else the default constructor is invoked automatically. For the assignment operator, it is accomplished by using the scope-resolution operator in an explicit call of the base-class assignment operator.

An Inheritance Example with Dynamic Memory Allocation and Friends

To illustrate these ideas of inheritance and dynamic memory allocation, let’s integrate the baseDMA, lacksDMA, and hasDMA classes just discussed into a single example. Listing 13.14 is a header file for these classes. To what we’ve already discussed, it adds a friend function that illustrates how derived classes can access friends to a base class.

Listing 13.14. dma.h

// dma.h  -- inheritance and dynamic memory allocation

#ifndef DMA_H_

#define DMA_H_

#include

//  Base Class Using DMA

class baseDMA

{

private:

    char * label;

    int rating;

public:

    baseDMA(const char * l = "null", int r = 0);

    baseDMA(const baseDMA & rs);

    virtual ~baseDMA();

    baseDMA & operator=(const baseDMA & rs);

    friend std::ostream & operator<<(std::ostream & os,

                                     const baseDMA & rs);

};

// derived class without DMA

// no destructor needed

// uses implicit copy constructor

// uses implicit assignment operator

class lacksDMA :public baseDMA

{

private:

    enum { COL_LEN = 40};

    char color[COL_LEN];

public:

    lacksDMA(const char * c = "blank", const char * l = "null",

              int r = 0);

    lacksDMA(const char * c, const baseDMA & rs);

    friend std::ostream & operator<<(std::ostream & os,

                                     const lacksDMA & rs);

};

// derived class with DMA

class hasDMA :public baseDMA

{

private:

    char * style;

public:

    hasDMA(const char * s = "none", const char * l = "null",

              int r = 0);

    hasDMA(const char * s, const baseDMA & rs);

    hasDMA(const hasDMA & hs);

    ~hasDMA();

    hasDMA & operator=(const hasDMA & rs);

    friend std::ostream & operator<<(std::ostream & os,

                                     const hasDMA & rs);

};

#endif

Listing 13.15 provides the method definitions for the baseDMA, lacksDMA, and hasDMA classes.

Listing 13.15. dma.cpp

// dma.cpp --dma class methods

#include "dma.h"

#include

// baseDMA methods

baseDMA::baseDMA(const char * l, int r)

{

    label = new char[std::strlen(l) + 1];

    std::strcpy(label, l);

    rating = r;

}

baseDMA::baseDMA(const baseDMA & rs)

{

    label = new char[std::strlen(rs.label) + 1];

    std::strcpy(label, rs.label);

    rating = rs.rating;

}

baseDMA::~baseDMA()

{

    delete [] label;

}

baseDMA & baseDMA::operator=(const baseDMA & rs)

{

    if (this == &rs)

        return *this;

    delete [] label;

    label = new char[std::strlen(rs.label) + 1];

    std::strcpy(label, rs.label);

    rating = rs.rating;

    return *this;

}

std::ostream & operator<<(std::ostream & os, const baseDMA & rs)

{

    os << "Label: " << rs.label << std::endl;

    os << "Rating: " << rs.rating << std::endl;

    return os;

}

// lacksDMA methods

lacksDMA::lacksDMA(const char * c, const char * l, int r)

    : baseDMA(l, r)

{

    std::strncpy(color, c, 39);

    color[39] = '\0';

}

lacksDMA::lacksDMA(const char * c, const baseDMA & rs)

    : baseDMA(rs)

{

    std::strncpy(color, c, COL_LEN - 1);

    color[COL_LEN - 1] = '\0';

}

std::ostream & operator<<(std::ostream & os, const lacksDMA & ls)

{

    os << (const baseDMA &) ls;

    os << "Color: " << ls.color << std::endl;

    return os;

}

// hasDMA methods

hasDMA::hasDMA(const char * s, const char * l, int r)

         : baseDMA(l, r)

{

    style = new char[std::strlen(s) + 1];

    std::strcpy(style, s);

}

hasDMA::hasDMA(const char * s, const baseDMA & rs)

         : baseDMA(rs)

{

    style = new char[std::strlen(s) + 1];

    std::strcpy(style, s);

}

hasDMA::hasDMA(const hasDMA & hs)

         : baseDMA(hs)  // invoke base class copy constructor

{

    style = new char[std::strlen(hs.style) + 1];

    std::strcpy(style, hs.style);

}

hasDMA::~hasDMA()

{

    delete [] style;

}

hasDMA & hasDMA::operator=(const hasDMA & hs)

{

    if (this == &hs)

        return *this;

    baseDMA::operator=(hs);  // copy base portion

    delete [] style;         // prepare for new style

    style = new char[std::strlen(hs.style) + 1];

    std::strcpy(style, hs.style);

    return *this;

}

std::ostream & operator<<(std::ostream & os, const hasDMA & hs)

{

    os << (const baseDMA &) hs;

    os << "Style: " << hs.style << std::endl;

    return os;

}

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги