继承和派生

1. 继承和派生一般性概念 
在一个已经存在的类的基础上建立一个新的类,新类从已有的类那里获取某些已有的特征,这种现象称为类的继承。从另一个角度说,从已有的类产生一个新的类,称为类的派生.

01class CBase
02{
03public:
04       int m_iBase;
05       int BaseFunc()
06              {
07                     return m_iBase;
08       }
09};
10   
11class CDerived:public CBase
12{
13public:
14              int m_iDerived;
15       int DerivedFunc()
16              {
17                     return m_iDerived;
18       }
19};


  
如上,CBase类派生了一个新的类CDerived,或者说类CDerived从类CBase继承而来,这样, 
类CDerived不但具有新增的成员m_iDerived和DerivedFunc(),还有从类CBase继承而来的成员 
m_iBase和BaseFunc(),从而类CDerived实际具有4个成员。 
  
派生类的一般声明形式为:

1class 派生类名:[继承方式] 基类名
2{
3              派生类新增的成员
4};


  
2. 类的继承方式 
派生类并非把基类的所有特性都继承下来。它还受两方面约束: 
1、 不论何种方式,下面这些基类的特征是不能从基类继承下来的: 
l         构造函数 
l         析构函数 
l         用户重载的new 运算符 
l         用户重载的=运算符 
l         友员关系 
  
2、 对基类的除(1)以外的其他成员的继承受继承方式限制,有三种继承的方式:私有继承、保护继承和公有继承。不同的继承方式将导致从基类继承来的成员在派生类中具有不同的访问限制属性。三种继承方式一般形式为:

01class 派生类名:private 基类名         //私有继承
02{
03        派生类新增成员
04};
05   
06class 派生类名:protected 基类名     //保护继承
07{
08        派生类新增成员
09};
10   
11class 派生类名:public 基类名          //公有继承
12{
13        派生类新增成员
14};


  
练习:写程序,推断在不同的继承方式下,派生类继承的基类成员的访问限制属性 
  
不同继承方式下的访问限制属性


继承方式

基类中的访问属性

派生类中的访问属性

公有继承

private

为基类私有

protected

保护类型

public

公有类型

保护继承

private

为基类私有

protected

保护类型

public

保护类型

私有继承

private

为基类私有

protected

私有类型

public

私有类型


  
3. 派生类对基类成员的覆盖 
如果基类和派生类中存在同名的成员数据或者成员函数,那么派生类的成员数据和成员函数将覆盖掉基类的成员数据和成员函数。而且与基类和派生类的访问属性无关;与基类和派生类的函数间的参数和返回类型无关。

01class CBase
02{
03protected:
04       int m_i;
05public:
06       int Func(int i)
07       {
08              return m_i;
09       }
10};
11   
12class CDerived:public CBase
13{
14public:
15       int m_i;                        //覆盖掉基类的m_i;
16       int Func()                            //覆盖掉基类的Func
17       {
18              m_i=9;                         //访问自身的成员
19              CBase::m_i=22;             //通过作用域解析符访问基类的成员
20              return m_i;
21       }
22};
23   
24void main()
25{
26       CDerived obj;
27       obj.Func();
28       //obj.Func(3);               //错误!基类的Func被覆盖
29       obj.CBase::Func(3);              //正确,通过作用域解析符访问基类的成员
30}


  
4. 派生类对象的初始化与清除 
如果需要在初始化派生类成员时也初始化基类的成员,则可在派生类的构造函数的初始化成员列表中初始化基类,如果基类的构造函数均带有参数,则基类必须出现在派生类的初始化成员列表中。 
派生类构造函数及初始化列表的一般形式为: 
  
派生类名(构造函数参数列表): 基类名(参数列表),派生类成员1(参数列表1),,,派生类成员n(参数列表n) 
例:

01class CBase
02{
03protected:
04       int m_iBase;
05public:
06       //CBase(){}
07       CBase(int i){m_iBase=i;}
08};
09   
10class CDerived:public CBase
11{
12public:
13       int m_iDerived;
14       CDerived(int i);
15};
16   
17CDerived::CDerived(int i):CBase(0),m_iDerived(i)
18{
19   
20}


  
执行派生类构造函数的顺序为: 
1、 调用基类的构造函数,初始化基类的数据成员; 
2、 初始化派生类的数据成员; 
3、 执行派生类的构造函数本身。 
  
派生类的析构函数相对简单       ,与无继承关系的普通类的析构函数形式相同。执行析构函数的顺序为: 
1、 调用派生类的析构函数; 
2、 调用基类的析构函数。 
  
5. 对象间的转换与赋值 
5.1. 派生类与基类间的转换 
正如整型数据可以自动转换成double型一样,基类对象与派生类对象间也存在赋值兼容的关系。具体表现在一下几个方面:

1class CBase
2{
3//...
4};
5class CDerived:public CBase
6{
7//...
8};


  
l          派生类对象可以向基类对象赋值; 
CBase base; 
CDerived derived; 
base=derived;          //将派生类对象的基类部分拷贝给基类对象 
  
l          派生类对象可以替代基类对象向基类对象的引用进行赋值或者初始化; 
CBase b1; 
CDerived d1; 
CBase &b1Alias=b1;     //普通的引用 
b1Alias=d1;            //将d1的基类部分拷贝给b1Alias(即b1) 
CBase &b2=d1;          //d1基类部分的引用 
  
l          如果函数的参数是基类对象或者基类对象的引用,则相应的实参可以是派生类对象。 

01void Func1(CBase base)
02{
03//...
04}
05void Func2(CBase &base)
06{
07//...
08}
09CDerived derived;
10Func1(derived);        //将derived的基类部分拷贝给行参base
11Func2(derived)              //将derived的基类部分当作行参使用

 
  
l          派生类对象的地址可以赋给基类类型的指针变量,或者说,基类型的指针可以指向派生类对象。 

1CBase *pBase;
2CDerived derived;
3pBase=&derived;

 
5.2. 派生类与派生类间的赋值(拷贝) 
如果用户定义了基类的拷贝构造函数,而没有定义派生类的拷贝构造函数,那么在用一个派生类对象初始化新的派生类对象时,两对象间的派生类部分执行缺省的行为,而两对象间的基类部分执行用户定义的基类拷贝构造函数。 
  
如果用户重载了基类的对象赋值运算符=,而没有定义派生类的对象赋值运算符,那么在用一个派生类对象给新的派生类对象赋值时,两对象间的派生类部分执行缺省的赋值行为,而两对象间的基类部分执行用户定义的重载赋值函数。 
如果用户定义了派生类的拷贝构造函数或者重载了派生类的对象赋值运算符=,则在用已有派生类对象初始化新的派生类对象时,或者在派生类对象间赋值时,将会执行用户定义的派生类的拷贝构造函数或者重载赋值函数,而不会再自动调用基类的拷贝构造函数和基类的重载对象赋值运算符,这时,通常需要用户在派生类的拷贝构造函数或者派生类的赋值函数中显式调用基类的相应函数。 
  
例:

01class CBase
02{
03protected:
04     char *m_pszData;
05public:
06     CBase(const char *pszData)
07     {
08         m_pszData=new char[strlen(pszData)+1];
09         strcpy(m_pszData,pszData);
10     }
11     CBase(const CBase &base)
12     {
13         m_pszData=new char[strlen(base.m_pszData)+1];
14         strcpy(m_pszData,base.m_pszData);
15     }
16     CBase &operator =(const CBase &base)
17     {
18         if(this==&base)
19              return *this;
20         m_pszData=new char[strlen(base.m_pszData)+1];
21         strcpy(m_pszData,base.m_pszData);
22         return *this;
23     }
24     ~CBase(){delete []m_pszData;}
25};
26   
27class CDerived:public CBase
28{
29public:
30     CDerived(const char *pszData):CBase(pszData){}
31};
32   
33void main()
34{1q                                                                                                                
35     CDerived d1("Hello!");
36     CDerived d2=d1;                      //派生类使用缺省的拷贝构造函数、基类调用用户定义的拷贝构造函数
37     d1=d2;                               //派生类使用缺省的赋值操作,基类调用用户重载的赋值运算符
38}


  
  
6. 保护构造函数与私有构造函数 
l         如果一个类的构造函数和析构函数是保护类型的,则不能在程序中实例化该类的对象,这样的类称为抽象类。由于保护的构造函数可以被派生类访问,所以我们通常将抽象类用于各种派生类的公共基类,使得该抽象类派生的类拥有共同的特性。

01class CAbstract
02{
03protected:
04       CAbstract(){}                      //保护类型的构造函数
05       //...
06};
07   
08class CDerived:public CAbstract
09{
10       //...
11};
12void main()
13{
14       //CAbstract objAbs;                     //错误,无法实例化
15       CDerived objDer;                  //可以
16}


  
l         如果类的构造函数是私有的,这样的类也是抽象类,但是因为派生类也无法调用它,从而无法用派生的方式初始化,但是可以用静态函数的方式实例化该类的对象。

01class CAbstract
02{
03private:
04       CAbstract(){}                      //保护类型的构造函数
05       //...
06public:
07       static CAbstract *CreateInstance()
08       {
09              return new CAbstract();
10       }
11       static void ReleaseInstance(CAbstract *pThis)
12       {
13              delete pThis;
14       }
15};
16   
17void main()
18{
19       CAbstract *pObj=CAbstract::CreateInstance();
20       //...
21       CAbstract::ReleaseInstance(pObj);
22}

 
7. 多重继承与虚基类 
7.1. 多重继承 
如果一个派生类同时有两个或者多个基类,派生类从两个和多个基类中继承所需的属性,这种继承方式称为多重继承(Multiple Inheritance)。 
声明多重继承的一般形式为:

1class 派生类名:继承方式1 基类名1,继承方式2 基类名2,,,继承方式n 基类名n
2{
3//... 派生类新增的成员。
4};

  
例:

01class CBaseA
02{
03public:
04       int m_i;
05       void Func()
06       {
07              m_i++;
08       }
09};
10   
11class CBaseB
12{
13public:
14       int m_i;
15       void Func()
16       {
17              m_i++;
18       }
19};
20   
21class CDerived:public CBaseA,public CBaseB
22{
23public:
24       int m_j;
25};


  
数据成员在内存中的布局形式为: 
  
pa


int m_i [CBaseA中的成员]

[CDerived]

int m_i [CBaseB中的成员]

int m_j 


pb 
  
  
  

调用时必须注意防止二义性:

01CDerived d;
02d.m_j=0;               //正常
03//i=d.m_i;                     //引起二义性
04d.CBaseA::m_i=1;   //通过成员民限定消除二义性,访问从CBaseA中继承来的m_i
05d.CBaseB::m_i=2;   //通过成员民限定消除二义性,访问从CBaseB中继承来的m_i
06//d.Func();                    //引起二义性
07d.CBaseA::Func(); //通过成员民限定消除二义性,访问从CBaseA中继承来的成员函数Func()
08d.CBaseB::Func(); //通过成员民限定消除二义性,访问从CBaseB中继承来的成员函数Func()
09CBaseA *pa;
10CBaseB *pb;
11pa=&d;                        //系统会自动将pa指向对象d的CBaseA部分
12pb=&d;                        //系统会自动将pb指向对象d的CBaseB部分

 
  
7.2. 虚基类 
如果一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在生成派生类对象时,系统会为派生类对象生成共同基类数据成员的多份拷贝。如果希望派生类对象中只包含一份共同基类的数据成员,则可以在声明派生类时,通过virtual继承方式,使派生对象只保留共同基类的一份数据成员。 
例:

01class CBase
02{
03public:
04     int m_i;
05};
06   
07class CBaseA:public CBase
08{
09public:
10     int m_ia;
11};
12   
13class CBaseB:public CBase
14{
15public:
16     int m_ib;
17};
18class CDerived: public CBaseA, public CBaseB
19{
20public:
21     int m_d;
22};


  
则内存布局形式为


int m_i

CBase

CBaseA

CDerived

int m_ia

int m_i

CBase

CBaseB

int m_ib

int m_id


  
  
而如果类CBaseA和CBaseB的声明形式为:

01class CBaseA:virtual public CBase
02{
03public:
04     int m_ia;
05};
06   
07class CBaseB:virtual public CBase
08{
09public:
10     int m_ib;
11};


  
  
 这样派生类对象可以直接使用公共基类的成员:

1CDerived d;
2d.m_i=9;

 

数据中心机房是现代信息技术的核心设施,它承载着企业的重要数据和服务,因此,其基础设计与规划至关重要。在制定这样的方案时,需要考虑的因素繁多,包括但不限于以下几点: 1. **容量规划**:必须根据业务需求预测未来几年的数据处理和存储需求,合理规划机房的规模和设备容量。这涉及到服务器的数量、存储设备的容量以及网络带宽的需求等。 2. **电力供应**:数据中心是能源消耗大户,因此电力供应设计是关键。要考虑不间断电源(UPS)、备用发电机的容量,以及高效节能的电力分配系统,确保电力的稳定供应并降低能耗。 3. **冷却系统**:由于设备密集运行,散热问题不容忽视。合理的空调布局和冷却系统设计可以有效控制机房温度,避免设备过热引发故障。 4. **物理安全**:包括防火、防盗、防震、防潮等措施。需要设计防火分区、安装烟雾探测和自动灭火系统,设置访问控制系统,确保只有授权人员能进入。 5. **网络架构**:规划高速、稳定、冗余的网络架构,考虑使用光纤、以太网等技术,构建层次化网络,保证数据传输的高效性和安全性。 6. **运维管理**:设计易于管理和维护的IT基础设施,例如模块化设计便于扩展,集中监控系统可以实时查看设备状态,及时发现并解决问题。 7. **绿色数据中心**:随着环保意识的提升,绿色数据中心成为趋势。采用节能设备,利用自然冷源,以及优化能源管理策略,实现低能耗和低碳排放。 8. **灾难恢复**:考虑备份和恢复策略,建立异地灾备中心,确保在主数据中心发生故障时,业务能够快速恢复。 9. **法规遵从**:需遵循国家和地区的相关法律法规,如信息安全、数据保护和环境保护等,确保数据中心的合法运营。 10. **扩展性**:设计时应考虑到未来的业务发展和技术进步,保证机房有充足的扩展空间和升级能力。 技术创新在数据中心机房基础设计及规划方案中扮演了重要角色。例如,采用虚拟化技术可以提高硬件资源利用率,软件定义网络(SDN)提供更灵活的网络管理,人工智能和机器学习则有助于优化能源管理和故障预测。 总结来说,一个完整且高效的数据中心机房设计及规划方案,不仅需要满足当前的技术需求和业务目标,还需要具备前瞻性和可持续性,以适应快速变化的IT环境和未来可能的技术革新。同时,也要注重经济效益,平衡投资成本与长期运营成本,实现数据中心的高效、安全和绿色运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值