继承与派生

代码重用是提高软件开发效率的重要手段,C++对代码重用有很强的支持,"继承"就是支持代码
  重用的机制之一。
       
  继承:通过继承我们能够定义一些共享公共部分(基类)但保留各自特殊部分的类。派生类能够继
  承基类定义的成员并使用它们。
  从一个类派生处另一个类的写法:
      class 派生类名:继承方式说明符 基类名{
       ......
   }
   
  protected说明符:基类的受保护成员可以在派生类的成员函数中被访问。
  在基类中一般将需要隐藏的成员说明为保护成员而非私有成员。
   
     继承方式:
      公用继承public:保留基类成员自己的访问级别
   受保护继承protected:基类的私有成员仍为私有,protected与public成员在派生类中为protected成员
   私有继承private:基类所有成员在派生类中都为私有成员
        一般情况下都是使用public继承。 
  
  正确处理不同类之间的关系:复合关系和继承关系
     复合关系:表现为封闭类,即一个类以另一个类的对象作为成员变量。
  继承关系:即基类对象与派生类对象之间之间的关系。
  
  再设计两个有关系的类时,并非只要两个类由共同点就让它们称为继承关系,让类B继承类A,必须
  满足类B代表的事物也是类A代表的事物。

class fruit{
    private:
        char *taste;
        double price;
    public:
        void Eat(char *name);
}; 

class apple:public fruit{
    private:
        char *area; 
};

 派生类的构造函数和析构函数:
     构造函数:
      派生类对象中包含基类对象,在创建派生类对象时,除了调用自身的构造函数进行初始
   化,还需要调用基类的构造函数初始化其包含的基类对象。
  
      在执行派生类的构造函数之前,总是先执行基类的构造函数。
   与说明封闭类对象如何初始化类似,派生类说明基类对象如何初始化也需要在构造函数
   后面添加初始化列表。在初始化列表中要指明调用基类构造函数的形式。写法:
       构造函数名(形参表):基类名(基类构造函数实参表){
           ......
       }
   
   派生类对象消亡时,先执行派生类对象的析构函数,在执行基类的析构函数。
   
   如果一个派生类对象是用默认复制构造函数初始化的,那么它内部包含的基类也要用基
   类的复制构造函数初始化。

#include <iostream>
#include <string>

using namespace std;

class fruit{
    private:
        string taste;
    public:
        fruit(string str):taste(str){
            cout << "Create Base Class" << endl;
        }
        ~fruit(){
            cout << "Destroy Base Class" << endl;
        }
};

class apple:public fruit{
    private:
        double price;
    public:
        // apple(){ };  编译错误    
        apple(double pr, string str):fruit(str),price(pr){
            cout << "Create Derived Class" << endl;
        } 
        ~apple(){
            cout << "Destroy Derived Class" << endl;
        }
}; 

int main()
{
    fruit f("Good");
    apple a(0.0, "Good");
    
    return 0;
}

多层次的派生:
     若类A派生出类B,类B派生出类C,则成类B为类C的直接基类,类A是类C的间接基
  类。以此类推,派生类沿着继承关系自动向上继承它的所有间接基类。
  
  派生类中的成员包括它内定义的成员和它基类定义的成员以及其间接基类中定义
  的所有成员。
  
  当派生类对象生成时会从最顶层的基类开始逐层执行所有基类的构造函数,当派
  生类消亡时,会先执行自身的析构函数,再自下而上执行其它基类的析构函数。
  
    包含成员对象的派生类:
     在派生类也是封闭类的情况下,构造函数的初始化列表不但要指明基类对象的初
  始化方式还要指明成员对象的初始化方式。顺序是自上而下的执行所有基类的构
  造函数,再按照成员对象的定义顺序执行各个成员对象的构造函数,最后执行自
  身的构造函数。当派生类对象消亡时,先执行自身的析构函数,然后按与构造次
  序相反的顺序执行所有成员对象的析构函数。在自下而上执行所有基类的析构函
  数。
  
 在共有继承的情况下:
     派生类对象可以复制给基类对象
  派生类对象可以用来初始化基类引用
  派生类对象的地址可以赋给基类指针
      即使基类指针指向一个派生类对象,但却不能通过基类指针访问基类没有而
   派生类中有的成员。
  
  在共有继承的情况下,可以说,派生类对象也是基类对象,任何本该出现基类对
  象的地方都可以使用派生类对象。
  
  基类引用也可以强制转化为派生类引,但具有安全隐患。
 
 派生类和复制运算:
     如果基类重载了复制运算符而派生类没有,那么在派生类对象之间赋值,或用派
  生类对象对基类对象进行赋值时,其中基类部分的赋值操作是调用基类重载的赋
  值运算符完成的。

#include <iostream>

using namespace std; 

class fruit{
    public:
        char *taste;
}; 

class apple:public fruit{
    public:
        double price; 
};

int main()
{
    apple a;
    fruit *pf1 = &a;
    fruit &pf2 = a;
    // cout << pf1->price << endl;  [Error] 'class fruit' has no member named 'price'
    fruit f;
    // apple *pa = &f; [Error] invalid conversion from 'fruit*' to 'apple*' [-fpermissive]
    
    return 0;
}
原文地址:https://www.cnblogs.com/lnlin/p/7637853.html