BigThree设计原则学习-对于派生类的处理

来源:互联网 发布:php项目经验描述 编辑:程序博客网 时间:2024/05/18 00:46

本文在[BigThree设计原则学习]的基础上对于派生类的情形进行讨论。

问题

对于派生类的情形,如果基类实现了BigTree,那么派生类应该怎么实现?需要自己再实现还是用系统默认的?

我自己的理解,派生类要对基类的初始化进行负责,因为派生类是基类的扩展,基类是派生类抽象上的自己,所以后者应对前者的行为负责。但是从层次上来看,二者并不在一个层次。虽然,当我们看派生类的时候,我们看的就是派生类,但是,派生类内部其实蕴含着基类。还是有一个层次关系在的。

所以,对于派生类而言,它是否需要实现BigThree,只需要看它所在的层次是否满足实现BigThree的时机,即是否需要管理动态开辟的内存。如果需要管理,则实现BigThree,反之,不需要。这是它唯一的判别标准。

比如,下面这段代码。
先不从建模的角度考虑我这么设计类是否合理,我只是为了说明派生类实现BigThree的实际。
Base:相当于一个班级信息类,包含学生数量和成绩数组两个成员变量。成绩数组是动态管理的。
Derived:派生于Base,增加了班级名称这个成员变量。

显然,根据上文我的讨论。从层次的角度看,是否需要实现BigThree只需看当前层次是否需要管理动态开辟的内存。Base需要管理(n_, arr_,其中arr_管理动态空间),所以要实现BigThree,Derived不需要管理(只需要管理name_,并不是指针类型),所以不需要实现,利用系统自己生成的即可。下面贴出代码。

代码

  • Test.h
#ifndef BASE_DERIVED_H#define BASE_DERIVED_H#include <string>class Base{public:    Base(){ std::memset( this, 0, sizeof(Base) ); }    Base( int len ) : n_(len) { arr_ = new int[len]; }public:    ~Base(){ dispose(); }    Base( const Base& rhs ){ copy_from( rhs ); }    Base& operator=( const Base& rhs ){        if( this != &rhs ){dispose(); copy_from(rhs);}        return *this;    }public:    void input_info();    void output_info();private:    void copy_from( const Base& rhs );    void dispose();private:    int n_;    int* arr_;};class Derived : public Base{public:    Derived(){}    Derived( int len, std::string name) : Base(len), name_(name) {}public:    void output_info();private:    std::string name_;};#endif
  • Test.cpp
#include <iostream>#include "Test.h"void Base::copy_from( const Base& rhs ){    std::memcpy( this, &rhs, sizeof(Base) );    if( rhs.arr_ ){        this->arr_ = new int[this->n_];        for( int i = 0; i < this->n_; ++i ){            this->arr_[i] = rhs.arr_[i];        }    }}void Base::dispose(){    if( this->arr_ ){        delete [] this->arr_;        this->arr_ = NULL;    }}void Base::input_info(){    std::cout << "请输入" << this->n_ << "名学生成绩:";    for( int i = 0; i < this->n_; ++i ){        std::cin >> this->arr_[i];    }}void Base::output_info(){    for( int i = 0; i < this->n_; ++i ){        std::cout << this->arr_[i] << " ";    }}void Derived::output_info(){    std::cout << this->name_ << " : ";    Base::output_info();}
  • main.cpp
#include <iostream>#include "Test.h"int main( void ){    Derived a;    Derived b(3, "15级1班");    b.input_info();    b.output_info();    std::cout << std::endl;    a = b;    a.output_info();    std::cout << std::endl;    Derived c(b);    c.output_info();    std::cout << std::endl;    return 0;}

下面则展示,如果派生类需要管理动态开辟内存情形时的代码。由于需要管理动态内存,所以肯定要实现BigThree。那么现在问题来了,既然基类要实现BigThree,派生类也要实现BigThree。那么他们两什么关系。

对于派生类而言,实现BigThree的时候,需要负责基类BigThree的实现。此时,只需要调用基类的相应BigThree函数(注意:不是copy_from和dispose这两个内存管理函数)并且实现当前层次动态开辟内存的管理即可。所以,派生类也要增加copy_from和dispose这两个内存管理函数。但是,他们只负责当前层次的动态开辟内存管理。

注意:我曾错误的只是完全试图使用copy_from和dispose解决问题,把基类内存的管理嵌套在派生类的copy_from和dispose当中解决。

  • Test.h
#ifndef BASE_DERIVED_H#define BASE_DERIVED_H#include <string>class Base{public:    Base(){ std::memset( this, 0, sizeof(Base) ); }    Base( int len ) : n_(len) { grade_ = new int[len]; }public:    ~Base(){ dispose(); }    Base( const Base& rhs ){ copy_from( rhs ); }    Base& operator=( const Base& rhs ){        if( this != &rhs ){dispose(); copy_from(rhs);}        return *this;    }public:    void input_info();    void output_info();    int get_n() const { return n_; }private:    void copy_from( const Base& rhs );    void dispose();private:    int n_;    int* grade_;};class Derived : public Base{public:    Derived(){this->age_ = NULL;}    Derived( int len, std::string name) : Base(len), name_(name) { age_ = new int[len]; }public:    ~Derived(){ dispose(); }    Derived( const Derived& rhs ) : Base(rhs) { copy_from(rhs); }    Derived& operator=( const Derived& rhs ){        if(this != &rhs){ Base::operator=(rhs);dispose(); copy_from(rhs); }        return *this;    }public:    void input_info();    void output_info();private:    void copy_from( const Derived& rhs );    void dispose();private:    std::string name_;    int* age_;};#endif
  • Test.cpp
#include <iostream>#include "Test.h"/* -----------------Base----------------------- */void Base::copy_from( const Base& rhs ){    std::memcpy( this, &rhs, sizeof(Base) );    if( rhs.grade_ ){// 是否有外部资源        this->grade_ = new int[this->n_];        for( int i = 0; i < this->n_; ++i ){            this->grade_[i] = rhs.grade_[i];        }    }}void Base::dispose(){    if( this->grade_ ){        delete [] this->grade_;        this->grade_ = NULL;    }}void Base::input_info(){    std::cout << "请输入" << this->n_ << "名学生成绩:";    for( int i = 0; i < this->n_; ++i ){        std::cin >> this->grade_[i];    }}void Base::output_info(){    for( int i = 0; i < this->n_; ++i ){        std::cout << this->grade_[i] << " ";    }}/* -----------------Derived----------------------- */void Derived::input_info(){    Base::input_info();    std::cout << "请输入" << this->get_n() << "名学生年龄:";    int n = this->get_n();    for( int i = 0; i < n; ++i ){        std::cin >> this->age_[i];    }}void Derived::output_info(){    std::cout << this->name_ << " : ";    Base::output_info();    int n = this->get_n();    for( int i = 0; i < n; ++i ){        std::cout << this->age_[i] << " ";    }}void Derived::copy_from( const Derived& rhs ){    this->name_ = rhs.name_;    if( rhs.age_ ){// 是否有外部资源        int n = this->get_n();        this->age_ = new int[n];        for( int i = 0; i < n; ++i ){            this->age_[i] = rhs.age_[i];        }    }}void Derived::dispose(){    if( this->age_ ){        delete [] this->age_;    }}
  • main.cpp
#include <iostream>#include "Test.h"int main( void ){    Derived a;    Derived b(3, "15级1班");    b.input_info();    b.output_info();    std::cout << std::endl;    a = b;    a.output_info();    std::cout << std::endl;    Derived c(b);    c.output_info();    std::cout << std::endl;    return 0;}

Introduction Programming with c++ P571给了一个模板。

Child::Child( const Child& object ) : parent(object){    // write the code for copying data fields in child}Child& Child::operator=( const Child& object ){    Parent::operator=(object);    // write the code for copying data fields in child}Child::~Child(){    // dispose data fields in child}
0 0
原创粉丝点击