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}
- BigThree设计原则学习-对于派生类的处理
- 类的设计原则
- 类的设计原则
- 类的设计原则
- 类的设计原则
- 类的设计原则
- 类的设计原则
- 类的设计原则
- 派生类的访问控制-“三看”原则-派生类类成员访问级别设置的原则
- 派生控件的处理。
- 学习面向对象的设计原则
- HTML5的学习资料(开发设计原则)
- 设计模式的六大原则学习
- blade中设计中对于HttpResponse的封装处理
- 抽象,派生类的学习笔记
- 基类、派生类的学习感悟
- C++ 学习(类的继承,派生)
- Java类的设计原则
- 创建线程的两种方式区别
- centos6.5安装高版本gcc
- leetcode 24. Swap Nodes in Pairs
- MySQL5.7.12新密码登录方式及密码策略
- 《C和指针》第四章学习摘要
- BigThree设计原则学习-对于派生类的处理
- Dynamic Programming 2
- PLSQL触发器
- 运行时验证工具汇总
- 关于编程风格和文档的扩展指南
- 天猫淘宝登陆页面无限循环 解决办法
- PIL修改图片
- 脱壳-MoleBox(2.0.0-2.3.0)
- windows下使用VS编译libIconv库