C++类继承

来源:互联网 发布:控制女高中生的软件 编辑:程序博客网 时间:2024/06/15 20:46

面向对象的编程的主要目的之一是提供可重用的代码。开发新项目,尤其是当项目十分庞大时,重用经过测试的代码比重新写代码要好得多。使用已有的代码可以节省时间,由于已有的代码已被使用和测试过,因此有助于避免在程序中引入错误。另外,必须考虑的细节越少,便能专注于程序的整体策略。

c++提供了比修改代码更好的方法来扩展和修改类,这种方法叫做类继承。它能够从已有的类派生出新的类,而派生类继承了原有类(基类)的特征,包括方法。正如从父辈那里继承来一笔财产总比自己去重新获取要来的简单的多。【示例1】

例如:

class A

{

};

A为基类,现在在A的的基础上再派生出一个新的类。

class B:public A

{

........

这里的冒号指出B类是由A类(基类)派生出来的新类,public表明A类是一个公有基类,这被称为公有派生。使用公有派生,基类的公有成员将成为派生类的公有成员;基类的私有部分也将成为派生类的一部分,但只能通过基类的公有和保护方法访问。

与此同时,派生类对象存储了基类的方法(派生类继承了基类的实现),也可以使用基类的方法(派生类继承了基类的接口)。

既然是派生类,不可能只有继承而没有添加新东西进来,那么派生类需要添加什么东西呢?

1、派生类自己的构造函数;

2、派生类可以根据实际情况添加额外的数据成员和成员函数。

构造函数必须给新成员和继承的成员提供数据。

要注意的是;派生类不能访问基类的私有成员,而必须通过基类的方法进行访问,这也就表明了如果派生类要访问基类的私有成员就必须要通过基类的构造函数来访问,那也就是说在创建派生类的对象时,程序首先创建基类对象。

现在假设有一个手机类Phone1,数据成员存储着手机的名字,型号,价格,以及是否在出售,然后派生类在原有的基础上添加了手机的颜色。

基类构造函数:

Phone1::Phone1(const string &n, const string &t, int p, bool sell)
{
name = n;
type = t;
price =p;
has_sell = sell;
}

派生类构造函数:

Phone2::Phone2(const string &c, const string &n, const string &t, int p, bool sell):Phone1(n,t,p,sell)
{
color = c;
}

这里的Phone1(n,t,p,sell)是成员初始化列表,它是可行代码,调用了基类的构造函数。也就是说,先要把实参传给基类构造函数的形参(n,t,p,sell),然后创建一个嵌套的基类对象,把数据存储在基类对象中,最后进入派生类构造函数体,完成派生类对象的创建,这就所谓的私有成员继承

或者是这样子的结构:

Phone2::Phone2(const string &c, const Phone1 &tp): Phone1(tp)
{
color = c;
}

这里tp为基类的复制构造函数,没有创建的话,系统会自己生成。

派生类构造函数小结:

1、首先要创建基类对象;

2、派生类构造函数应通过成员初始化列表将基类的信息传递给基类的构造函数;

3、派生类构造函数应初始化派生类新增的数据成员。

注意:创建派生类对象时,先进入基类构造函数,然后再调用派生类构造函数。基类的构造函数负责初始化继承的数据成员,而派生类构造函数则用于初始化新增的数据成员;但是如果派生类对象过期时,调用析构函数的顺序将会反过来,先调用派生类的,然后才是基类的。

---------------------------------------------------------分割线------------------------------------------------------

多态公有继承【示例2】

如果同一个方法在派生类和基类中不一样,方法的行为应取决于调用该方法的对象,这种复杂的行为成为多态。

实现多态公有继承的方法有两种:

1、在派生类中重新定义基类的方法;

2、使用虚方法

这里重点讲一下虚方法。

当基类和派生类中都含有同名方法(成员函数)时,但是方法中的内容却不一样,这时就需要使用关键字virtual,那么这种方法也就成为虚函数或者虚方法(virtual method)。

既然出现同名的函数,那么调用哪一个函数就成了问题,到底是调用基类的,还是派生类的。这里有一个选择标准:

1、如果没有使用关键字virtual,程序将根据引用类型或者指针类型选择方法;

2、如果使用了virtual,程序将根据引用或者指针指向的对象的类型来选择调用那个方法。

  • 不使用关键字virtual
假设A为基类,B为派生类,函数为hello()
A a=("love",12);
B b=("fuck",24);
A &c1=a;
A &c2=b;
c1.hello();
c2.helo();
这里c1和c2调用的都是A的hello()函数,因为c1和c2都是A类引用对象,如果换成指针也是一样的,这里的引用和指针要满足一种关系,基类的引用对象可以是自己的对象也可以是派生类对象,但是派生类的引用对象只能是自己的对象,而不能反过来。
  • 使用关键字virtual
A a=("love",12);
B b=("fuck",24);
A &c1=a;
A &c2=b;
c1.hello();
c2.helo();
这里c1调用的是A::hello(),而c2调用的是B::hello()。因为有了关键字virtual之后,程序就根据对象类型来调用函数。
因此,为了更好的调用基类和派生类中的同名函数,最好是将基类的方法定义为虚函数,在函数前面加上关键字virtual,那么程序就将根据对象类型来确定调用那个该函数。
如果没有用指针和引用该怎么调用函数呢?
按道理来说,派生类对象是可以调用任意一个,因为它继承了基类的成员,但是我测试过,就是直接根据对象来的,是谁的对象就调用哪个函数,有点纳闷,
是优先选择吗?相比较而言,加上引用和指针以及virtual和没加上感觉是一样的。

前面说到过派生类的构造函数可以通过调用基类的构造函数来创建对象,并且使用成员初始化列表的方法来将基类中的信息传递给基类构造函数,然后使用构造函数体来
初始化新增的数据项。但是非构造函数是不能用这种方法的。如果要使用基类的函数可以用作用域解析运算符来调用,这个算是公有成员函数继承
A::hello();
----------------------------------------------------分割线-----------------------------------------------------------------

静态联编和动态联编

【代码示例一】

#include <iostream>#include <cstdlib>#include <string>#include <ctime>using namespace std;class Phone1{private:string name;string type;int price;bool has_sell;public:Phone1();Phone1(const string &n, const string &t, int p, bool sell);void Name() const { cout << "\t\t\t手机品牌:"<<name<<" "; }void Type() const { cout << "型号:"<<type<<" "; }void Price() const{ cout << "价格:" << price << "元 "; }bool hassell() const { return has_sell; }};class Phone2:public Phone1{private:string color;public:Phone2(const string &c, const string &n, const string &t, int p, bool sell);Phone2(const string &c, const Phone1 &tp);void Color() { cout << "颜色:"<<color<<" "; }};Phone1::Phone1(){}Phone1::Phone1(const string &n, const string &t, int p, bool sell){name = n;type = t;price =p;has_sell = sell;}Phone2::Phone2(const string &c, const string &n, const string &t, int p, bool sell):Phone1(n,t,p,sell){color = c;}Phone2::Phone2(const string &c, const Phone1 &tp): Phone1(tp){color = c;}int main(){Phone1 phone1 = {"HUAWEI","P9",3999,true};Phone2 phone2 = {"Black","XIAOMI","7",2999,false};Phone2 phone3 = {"Red",phone1 };cout << "\t\t\t\t欢迎来到磊神手机专卖店!"<<endl;struct tm *ptr;time_t lt;lt = time(NULL);ptr = gmtime(<);cout << "\n\t\t\t国际时间:";printf(asctime(ptr));cout << "\t\t\t北京时间:";printf(ctime(<));cout << "\n";phone1.Name();phone1.Type();if (phone1.hassell()){cout << "正在热卖中"<<endl;}else{cout << "还未销售" << endl;}phone2.Name();phone2.Type();phone2.Color();if (phone2.hassell()){cout << "正在热卖中" << endl;}else{cout << "还未销售" << endl;}phone3.Name();phone3.Type();phone3.Color();if (phone3.hassell()){cout << "正在热卖中" << endl;}else{cout << "还未销售" << endl;}//显示时间struct tm *local;time_t t;t = time(NULL);local = localtime(&t);printf("Local hour is: %d",local->tm_hour); local = gmtime(&t);printf("UTC hour is: %d",local->tm_hour); cout << "\n";system("pause");return 0;}
【演示结果】



【代码示例2】

#include <iostream>  #include <cstdlib>  #include <string>  #include <ctime>  using namespace std;class Phone1{private:string name;string type;int price;bool has_sell;int sell_num;public:Phone1();Phone1(const string &n, const string &t, int p, bool sell,int num);void Name() const { cout << "\t\t\t手机品牌:" << name << " "; }void Type() const { cout << "型号:" << type << " "; }int Sell() const { return sell_num; }int Price1() const { return price; }void Price() const { cout << "价格:" << price << "元 "; }void Had_sell() const {cout << "出售量:" <<sell_num<< "部 "; }bool hassell() const { return has_sell; }};class Phone2 :public Phone1{private:string color;//int sum;public:Phone2( const string &n, const string &t, int p, bool sell,int num);Phone2( const Phone1 &tp);//void Color() { cout << "颜色:" << color << " "; }void Had_sell() const {Phone1::Had_sell();cout << "盈利:" << (Phone1::Price1())*(Phone1::Sell())<< "元";}};Phone1::Phone1(){}Phone1::Phone1(const string &n, const string &t, int p, bool sell,int num){name = n;type = t;price = p;has_sell = sell;sell_num = num;}Phone2::Phone2(const string &n, const string &t, int p, bool sell,int num) :Phone1(n, t, p,sell,num){;}Phone2::Phone2(const Phone1 &tp) : Phone1(tp){;}int main(){Phone1 phone1 = { "HUAWEI","P9",3999,true,1000 };Phone2 phone2 = { "XIAOMI","7",2999,false,0 };Phone2 phone3 = { phone1 };Phone2 &a = phone2;Phone1 &b = phone1;cout << "\t\t\t\t欢迎来到磊神手机专卖店!" << endl;struct tm *ptr;time_t lt;lt = time(NULL);ptr = gmtime(<);cout << "\n\t\t\t国际时间:";printf(asctime(ptr));cout << "\t\t\t北京时间:";printf(ctime(<));cout << "\n";phone1.Name();phone1.Type();if (phone1.hassell()){cout << "正在热卖中 ";}else{cout << "还未销售 ";}phone1.Price();phone1.Had_sell();cout <<"\n\n";phone2.Name();phone2.Type();//phone2.Color();if (phone2.hassell()){cout << "正在热卖中 ";}else{cout << "还未销售 ";}phone2.Price();phone2.Had_sell();cout <<"\n\n";phone3.Name();phone3.Type();//phone3.Color();if (phone3.hassell()){cout << "正在热卖中 ";}else{cout << "还未销售 ";}phone3.Price();phone3.Had_sell();cout << endl;//显示时间  struct tm *local;time_t t;t = time(NULL);local = localtime(&t);printf("Local hour is: %d", local->tm_hour);local = gmtime(&t);printf("UTC hour is: %d", local->tm_hour);cout << "\n";system("pause");return 0;}

原创粉丝点击