亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++教程:C++繼承的實現和方式

2020-05-23 14:25:35
字體:
來源:轉載
供稿:網友
了解繼承的概念之后,我們就來學習一下如何實現繼承。

私有和保護

在第14章中我們說到,成員函數或成員數據可以是公有或者私有的。如果是公有的,那么它們可以被直接訪問;如果是私有的,那么它們無法被直接訪問。同時,我們還提到一個protected保留字,在沒有使用繼承的時候,它與private的效果是一樣的,即無法被直接訪問。如果使用了繼承,我們就能體會到protected和private的差別。

private(私有)和protected(保護)都能實現類的封裝性。private能夠對外部和子類保密,即除了成員所在的類本身可以訪問之外,別的都不能直接訪問。protected能夠對外部保密,但允許子類直接訪問這些成員。public、private和protected對成員數據或成員函數的保護程度可以用下表來描述:
C++教程:C++繼承的實現和方式

所以,當我們使用到繼承的時候,必須考慮清楚:成員數據或成員函數到底應該是私有的還是保護的。

一個簡單的例子

首先我們以一個學生類為例,介紹繼承的寫法:(程序17.3.1)
//student.h
#include <iostream>
using namespace std;
class student//學生類作為父類
{
   public:
   student(char *n,int a,int h,int w);//帶參數的構造函數
   student();//不帶參數的構造函數
   void set(char *n,int a,int h,int w);//設置
   char * sname();
   int sage();
   int sheight();
   int sweight();
   protected:
   char name[10];//姓名
   int age;//年齡
   int height;//身高
   int weight;//體重
   private:
   int test;
};
char * student::sname()
{
   return name;
}
int student::sage()
{
   return age; 
}
int student::sheight()
{
   return height;
}
int student::sweight()
{
   return weight;
}
void student::set(char *n,int a,int h,int w)
{
   int i;
   for (i=0;n[i]!='/0';i++)
   {
      name[i]=n[i];
   }
   name[i]='/0';
   age=a;
   height=h;
   weight=w;
   return;
}
student::student(char *n,int a,int h,int w)
{
   cout <<"Constructing a student with parameter..." <<endl;
   set(n,a,h,w);
}
student::student()
{
   cout <<"Constructing a student without parameter..." <<endl;
}
//undergraduate.h
#include "student.h"
class Undergraduate:public student//本科生類作為子類,繼承了學生類
{
   public:
   double score();
   void setGPA(double g);//設置績點
   bool isAdult();//判斷是否成年
   protected:
   double GPA;//本科生績點
};
double Undergraduate::score()
{
   return GPA;
}
void Undergraduate::setGPA(double g)
{
   GPA=g;
   return;
}
bool Undergraduate::isAdult()
{
   return age>=18?true:false;//子類訪問父類的保護成員數據
}
//main.cpp
#include <iostream>
#include "undergraduate.h"
using namespace std;
int main()
{
   Undergraduate s1;//新建一個本科生對象
   s1.set("Tom",21,178,60);
   s1.setGPA(3.75);
   cout <<s1.sname() <<endl;
   cout <<s1.sage() <<endl;
   cout <<s1.sheight() <<endl;
   cout <<s1.sweight() <<endl;
   cout <<s1.score() <<endl;
   cout <<s1.isAdult() <<endl;
   return 0;
}

運行結果:
Constructing a student without parameter...
Tom
21
178
60
3.75
1
在使用繼承之前,我們必須保證父類是已經定義好的。如果父類是虛無的、沒有被定義的,那么子類也就沒什么好繼承的了。定義一個子類的語法格式為:
    class 子類名:繼承方式父類名;
根據程序17.3.1的運行結果,我們可以清楚地看到,學生類里面的公有和保護成員都已經被繼承到本科生類。本科生類可以使用學生類的成員函數,也可以訪問學生類的保護成員。而本科生類中定義的成員則是對學生類的補充,并且也能夠被使用。

繼承的方式

在程序17.3.1中,我們選擇的繼承方式是public。和成員的類型一樣,除了public之外,繼承方式還有protected和private。那么,這三種繼承方式到底有什么區別呢?

public是公有繼承,或稱為類型繼承。它主要體現的是概念的延伸和擴展,父類所有的公有、保護成員都將按部就班地繼承到子類中。父類的公有成員在子類中依然是公有的,父類的保護成員在子類中依然是保護的。比如程序17.3.1中的學生類和本科生類就是這樣的關系。

private是私有繼承,或稱為私有的實現繼承。它主要體現的是父類成員的重用。父類所有的公有、保護成員繼承到子類時,類型會發生改變。父類的公有成員在子類中變成了私有成員,父類的保護成員在子類中也變成了私有成員。這時,我們可以利用從父類繼承而來的成員函數來實現子類的成員函數,并且不必擔心外部直接訪問父類的成員函數,破壞了子類的秩序。比如我們認為棧是一種特殊的鏈表,它只能從鏈表尾部添加或刪除結點,棧的壓棧和退棧功能可以方便地由鏈表類的成員函數實現。但是,如果外部還能直接訪問從鏈表類繼承而來的成員函數,那么就可以在棧的任何位置插入結點,棧就會被破壞。

protected是保護繼承,或稱為保護的實現繼承。與私有繼承類似,它也是體現父類成員的重用。只不過父類的公有成員和保護成員在子類中都變成了保護成員。因此,如果有一個孫類繼承了子類,那么父類中的成員也將被繼承,成為孫類的保護成員。

public、private和protected三種繼承方式可以用下表描述。其中右下角的九個單元格表示各種父類成員在對應的繼承方式下,成為子類成員后的性質。
C++教程:C++繼承的實現和方式
在使用繼承的時候,我們必須根據實際需要選擇合適的繼承方式。下面我們以棧繼承鏈表為例,理解一下私有繼承方式:(程序17.3.2)
//node.h
#include <iostream>
using namespace std;
class Node
{
friend class Linklist;//鏈表類作為友元類
friend class Stack;//棧類作為友元類
public:
Node();
Node(Node &n);
Node(int i,char c='0');
Node(int i,char c,Node *p,Node *n);
~Node();
private:
int idata;
char cdata;
Node *prior;
Node *next;
};
Node::Node()
{
cout <<"Node constructor is running..." <<endl;
idata=0;
cdata='0';
prior=NULL;
next=NULL;
}
Node::Node(int i,char c)
{
cout <<"Node constructor is running..." <<endl;
idata=i;
cdata=c;
prior=NULL;
next=NULL;
}
Node::Node(int i,char c,Node *p,Node *n)
{
cout <<"Node constructor is running..." <<endl;
idata=i;
cdata=c;
prior=p;
next=n;
}
Node::Node(Node &n)
{
idata=n.idata;
cdata=n.cdata;
prior=n.prior;
next=n.next;
}
Node::~Node()
{
cout <<"Node destructor is running..." <<endl;
}
//linklist.h
#include "node.h"
#include <iostream>
using namespace std; 
class Linklist
{
public:
Linklist(int i=0,char c='0');
Linklist(Linklist &l);
~Linklist();
bool Locate(int i);
bool Locate(char c);
bool Insert(int i=0,char c='0');
bool Delete();
void Show();
void Destroy();
protected://原私有成員改為保護成員,以便于Stack類繼承
Node head;
Node * pcurrent;
};
Linklist::Linklist(int i,char c):head(i,c)
{
cout<<"Linklist constructor is running..."<<endl;
pcurrent=&head;
}
Linklist::Linklist(Linklist &l):head(l.head)
{
cout<<"Linklist Deep cloner running..." <<endl;
pcurrent=&head;
Node * ptemp1=l.head.next;
while(ptemp1!=NULL)
{
Node * ptemp2=new Node(ptemp1->idata,ptemp1->cdata,pcurrent,NULL);
pcurrent->next=ptemp2;
pcurrent=pcurrent->next;
ptemp1=ptemp1->next;
}
}
Linklist::~Linklist()
{
cout<<"Linklist destructor is running..."<<endl;
Destroy();
}
bool Linklist::Locate(int i)
{
Node * ptemp=&head;
while(ptemp!=NULL)
{
if(ptemp->idata==i)
{
pcurrent=ptemp;
return true;
}
ptemp=ptemp->next;
}
return false;
}
bool Linklist::Locate(char c)
{
Node * ptemp=&head;
while(ptemp!=NULL)
{
if(ptemp->cdata==c)
{
pcurrent=ptemp;
return true;
}
ptemp=ptemp->next;
}
return false;
}
bool Linklist::Insert(int i,char c)
{
if(pcurrent!=NULL)
{
Node * temp=new Node(i,c,pcurrent,pcurrent->next);
if (pcurrent->next!=NULL)
{
pcurrent->next->prior=temp;
}
pcurrent->next=temp;
return true;
}
else
{
return false;
}
}
bool Linklist::Delete()
{
if(pcurrent!=NULL && pcurrent!=&head)
{
Node * temp=pcurrent;
if (temp->next!=NULL)
{
temp->next->prior=pcurrent->prior;
}
temp->prior->next=pcurrent->next;
pcurrent=temp->prior;
delete temp;
return true;
}
else
{
return false;
}
}
void Linklist::Show()
{
Node * ptemp=&head;
while (ptemp!=NULL)
{
cout <<ptemp->idata <<'/t' <<ptemp->cdata <<endl;
ptemp=ptemp->next;
}
}
void Linklist::Destroy()
{
Node * ptemp1=head.next;
while (ptemp1!=NULL)
{
Node * ptemp2=ptemp1->next;
delete ptemp1;
ptemp1=ptemp2;
}
head.next=NULL;
}
//stack.h
#include "linklist.h"
class Stack:private Linklist//私有繼承鏈表類
{
public:
bool push(int i,char c);
bool pop(int &i,char &c);
void show();
};
bool Stack::push(int i,char c)
{
while (pcurrent->next!=NULL)
pcurrent=pcurrent->next;
return Insert(i,c);//用鏈表類的成員函數實現功能
}
bool Stack::pop(int &i,char &c)
{
while (pcurrent->next!=NULL)
pcurrent=pcurrent->next;
i=pcurrent->idata;
c=pcurrent->cdata;
return Delete();//用鏈表類的成員函數實現功能
}
void Stack::show()
{
Show();//用鏈表類的成員函數實現功能
}
//main.cpp
#include <iostream>
#include "stack.h"
int main()
{
Stack ss;
int i,j;
char c;
for (j=0;j<3;j++)
{
cout <<"請輸入一個數字和一個字母:" <<endl;
cin >>i >>c;
if (ss.push(i,c))
{
cout <<"壓棧成功!" <<endl;
}
}
ss.show();
while (ss.pop(i,c))
{
cout <<"退棧數據為i=" <<i <<" c=" <<c <<endl;
}
return 0;
}
運行結果:
Node constructor is running...
Linklist constructor is running...
請輸入一個數字和一個字母:
1 a
Node constructor is running...
壓棧成功!
請輸入一個數字和一個字母:
2 b
Node constructor is running...
壓棧成功!
請輸入一個數字和一個字母:
3 c
Node constructor is running...
壓棧成功!
0 0
1 a
2 b
3 c
Node destructor is running...
退棧數據為i=3 c=c
Node destructor is running...
退棧數據為i=2 c=b
Node destructor is running...
退棧數據為i=1 c=a
Linklist destructor is running...
Node destructor is running...

我們看到,Stack類私有繼承了Linklist類之后,利用Linklist的成員函數,方便地實現了壓棧和退棧功能。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品视频久久久| 国产精品电影网站| 中文字幕精品一区二区精品| 在线亚洲欧美视频| 欧美亚洲另类在线| 亚洲性69xxxbbb| 亚洲自拍欧美另类| 久久韩国免费视频| 亚洲白虎美女被爆操| 欧美人与性动交a欧美精品| 欧美激情一区二区三区久久久| 欧美精品videosex极品1| 国产在线999| 国产精品视频网站| 国产精品免费久久久久久| 国产精品三级久久久久久电影| 亚洲无亚洲人成网站77777| 97香蕉久久超级碰碰高清版| 欧美成人精品在线观看| 97精品在线视频| 日韩免费观看视频| 国产一区二区欧美日韩| 色婷婷综合久久久久中文字幕1| 成人精品一区二区三区电影免费| 国产美女高潮久久白浆| 国产最新精品视频| 国产欧美精品一区二区三区-老狼| 自拍偷拍亚洲一区| 国产精品香蕉av| 精品久久中文字幕久久av| 久久偷看各类女兵18女厕嘘嘘| 尤物九九久久国产精品的分类| 亚洲国产日韩精品在线| 九九精品在线视频| 91精品国产综合久久久久久久久| 热久久免费视频精品| 日韩欧美在线字幕| 国产成人精品免费视频| 亚洲字幕在线观看| 成人国产精品久久久| 亚洲欧美一区二区三区在线| 欧美日韩免费一区| 久久综合国产精品台湾中文娱乐网| 高清欧美性猛交xxxx| 亚洲最大福利视频网站| 久久久人成影片一区二区三区观看| www.xxxx欧美| 91av网站在线播放| 欧美裸体视频网站| 欧美亚洲第一区| 亚洲日本成人网| 91中文精品字幕在线视频| 欧美激情精品久久久久久蜜臀| 久久成人这里只有精品| 午夜精品久久久久久99热软件| 成人h猎奇视频网站| 久久久精品国产亚洲| 亚洲精选中文字幕| 国产精品丝袜久久久久久不卡| 4388成人网| 中文字幕精品—区二区| 欧美成人激情视频免费观看| 91亚洲午夜在线| 日本高清+成人网在线观看| 91精品国产99| 欧美日韩免费观看中文| 97视频com| 欧美黑人xxxⅹ高潮交| 538国产精品一区二区免费视频| 欧美日韩国产一区二区三区| xxxxxxxxx欧美| 国产视频一区在线| 亚洲丝袜av一区| 欧美亚洲国产成人精品| 亚洲免费影视第一页| 久久精品视频中文字幕| 亚洲国产成人av在线| 视频一区视频二区国产精品| 久久影视免费观看| 亚洲最新av网址| 尤物九九久久国产精品的特点| 国产一区二区三区久久精品| 欧美日韩成人网| 黑人巨大精品欧美一区免费视频| 亚洲日韩中文字幕在线播放| 日韩视频精品在线| 国产精品久久久91| 国产黑人绿帽在线第一区| 亚洲人成电影在线播放| 国产精品永久免费在线| 日韩av快播网址| 欧美电影电视剧在线观看| 久久这里只有精品99| 国产精品av在线| 亚洲女人天堂成人av在线| 精品亚洲一区二区三区四区五区| 精品成人乱色一区二区| 国产精品久久久久久久久借妻| 蜜臀久久99精品久久久久久宅男| 国产精品都在这里| 国产免费一区二区三区在线能观看| 久久国产精彩视频| 国a精品视频大全| 亚洲精品一区在线观看香蕉| 亚洲免费电影一区| 97视频在线观看免费| 亚洲人精选亚洲人成在线| 青青在线视频一区二区三区| 91av视频在线| 亚洲第一男人av| 国产一区视频在线播放| 欧美亚洲另类视频| 欧美高清无遮挡| 欧美做受高潮电影o| 在线视频免费一区二区| 欧美激情视频网站| 欧美尺度大的性做爰视频| 亚洲精品视频免费| 亚洲成人中文字幕| 欧美激情一区二区三区在线视频观看| 在线视频日本亚洲性| 亚洲第一区在线| 在线观看欧美日韩国产| 国产日韩欧美黄色| 亚洲性69xxxbbb| 欧美激情亚洲综合一区| 日韩av网址在线观看| 萌白酱国产一区二区| 欧美国产日韩一区| 精品久久久91| 日韩欧美a级成人黄色| 亚洲精品www久久久| 欧美极品少妇xxxxⅹ裸体艺术| 日韩欧美在线观看视频| 国产主播喷水一区二区| 久久手机精品视频| 亚洲国产精品悠悠久久琪琪| 国产一区二区三区在线播放免费观看| 人九九综合九九宗合| 亚洲自拍另类欧美丝袜| 最近2019年日本中文免费字幕| 亚洲第一天堂无码专区| 亚洲国产精品va在看黑人| 久久久亚洲国产| 国产精品夜色7777狼人| 久久天天躁狠狠躁夜夜av| 一本久久综合亚洲鲁鲁| 最近2019年手机中文字幕| 日韩欧美精品中文字幕| 国产欧美精品日韩| 亚洲欧美日韩在线高清直播| 最近免费中文字幕视频2019| 亚洲一区二区三区香蕉| 亚洲第一网中文字幕| 国产日韩精品在线观看| 国产成人拍精品视频午夜网站| 狠狠色香婷婷久久亚洲精品| 亚洲欧美在线免费观看| 亚洲男人的天堂在线播放| 成人久久久久久久| 精品色蜜蜜精品视频在线观看| 日韩av最新在线| 91色视频在线导航| 2024亚洲男人天堂|