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

本文在[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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值