日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 嵌入式 > wenzi嵌入式軟件
[導(dǎo)讀]本文將敘述 C 的另一個(gè)內(nèi)容,也就是抽象,這也是 C 相對(duì)于 C語言來說獨(dú)特的一點(diǎn)。

前言

在上一則教程中,敘述了關(guān)于C 類型轉(zhuǎn)換的相關(guān)內(nèi)容,在本節(jié)教程中,將敘述?C 的另一個(gè)內(nèi)容,也就是抽象,這也是?C 相對(duì)于?C語言來說獨(dú)特的一點(diǎn),下面我們就來著重?cái)⑹鲞@一點(diǎn)。

純虛函數(shù)

在介紹抽象類之前,需要弄明白何為純虛函數(shù),下面假定我們有這樣一個(gè)需求:

做一個(gè)“各個(gè)國家的人的調(diào)查”,調(diào)查各個(gè)國家的人的:飲食、穿衣、開車

要完成這樣一個(gè)事情,那我們現(xiàn)在就需要實(shí)現(xiàn)這樣幾個(gè)類,一個(gè)是?Human類,其他國家的人從?Human類里派生而來,就比如說是ChineseEnglishman,我們?cè)倩剡^頭來想,我們所要實(shí)現(xiàn)的需求是調(diào)查各個(gè)國家的人,那么這個(gè)過程中,由Human類派生得到?Chinese和?Englishman,那么在實(shí)例化對(duì)象的時(shí)候,我們實(shí)際上是不會(huì)用到Human類去定義一個(gè)對(duì)象的,考慮到這層因素,我們?cè)?Human類里使用到了純虛函數(shù)的概念,類實(shí)現(xiàn)的代碼如下所示:

class?Human
{

private:
????int?a;
public:
????/*純虛函數(shù)*/
????virtual?void?eating(void)?=?0;
????virtual?void?wearing(void)?=?0;
????virtual?void?driving(void)?=?0;
};

class?Englishman?:?public?Human
{
public:
????void?eating(void)??{?cout<<"use?knife?to?eat"<<endl;?}
????void?wearing(void)?{cout<<"wear?english?style"<<endl;?}
????void?driving(void)?{cout<<"drive?english?car"<<endl;?}
};

class?Chinese?:?public?Human?
{
public:
????void?eating(void)??{?cout<<"use?chopsticks?to?eat"<<endl;?}
????void?wearing(void)?{cout<<"wear?chinese?style"<<endl;?}
????void?driving(void)?{cout<<"drive?chinese?car"<<endl;?}
};
我們可以看到在上述的代碼中,Human類的成員函數(shù)跟前幾講所寫的成員函數(shù)有所不同,而如上述?Human類的成員函數(shù)這般寫法,也就被稱之為是純虛函數(shù)

抽象類

上述引出了純虛函數(shù)的寫法,那純虛函數(shù)和抽象類之間有什么關(guān)系呢?實(shí)際上,抽象類就是具有純虛函數(shù)的類,那這抽象類存在的意義是什么呢?總的來說,其作用也就是:向下定義好框架,向上提供統(tǒng)一的接口,其不能夠?qū)嵗瘜?duì)象,基于上述幾個(gè)類的前提下,我們編寫主函數(shù)的代碼:

int?main(int?argc,char?**argv)
{
????Human?h;

????return?0;
}
因?yàn)槌橄箢惒荒軌驅(qū)嵗瘜?duì)象,所以上述代碼編譯結(jié)果是錯(cuò)誤的,錯(cuò)誤信息如下所示:

而使用通過抽象類派生得到的派生類實(shí)例化對(duì)象是可行的,代碼如下所示:

int?main(int?argc,?char**?argv)
{
????Englishman?e;
????Chinese????g;

????return?0;
}
另外需要注意的是:在派生抽象類的過程中,如果派生得到的子類沒有覆寫所有的純虛函數(shù),那么這個(gè)子類還是抽象類,比如有如下所示的代碼,Human類沿用的是上述的寫法,代碼不變,如果我們將上述的?Chinese類進(jìn)行更改,更改后的代碼如下所示:

class?Chinese?:?public?Human?
{
public:
????void?eating(void)?{?cout<<"use?chopsticks?to?eat"<<endl;?}
????void?wearing(void)?{cout<<"wear?chinese?style"<<endl;?}
????//void?driving(void)?{cout<<"drive?chinese?car"<
};
如上述代碼所示,我們將?driving()函數(shù)注釋掉了,那么也就是說,我們并沒有將抽象類的全部純虛函數(shù)進(jìn)行覆寫,那么當(dāng)前這個(gè)Chinese類也是一個(gè)抽象類,也是不能夠進(jìn)行實(shí)例化對(duì)象的,要使得?Chinese類有作用,我們必須派生出來另一個(gè)類,代碼如下所示:

class?Guangximan?:?public?Chinese?
{
????void?driving(void)?{cout<<"drive?guangxi?car"<<endl;?}
};
這個(gè)時(shí)候,就可以用?Guangximan這個(gè)類來實(shí)例化對(duì)象了。

多文件編程

在前面的教程中,有一則教程說到了多文件編程,在?C 中也就是將類的聲明放到頭文件中,將類的實(shí)現(xiàn)放在.cpp文件中,為了更好地闡述這種方法,我們用實(shí)例來進(jìn)行講解,首先,來看一下,所涉及到地所有文件有哪些:

image-20210222103409774
可以看到上述有6個(gè)文件,我們首先來看?Chinese.h這個(gè)文件,代碼如下所示:

#ifndef?_CHINESE_H
#define?_CHINESE_H

#include?
#include?
#include?

using?namespace?std;

class?Chinese
{

public:
????void?eating(void);?
????void?wearing(void);
????void?drivering(void);
};

#endif
通過上述地.h文件可以看出,在這里的Chinese類中,它只涉及到類成員函數(shù)的一個(gè)聲明,并沒有成員函數(shù)的實(shí)現(xiàn),我們繼續(xù)來看Chinese.cpp的類實(shí)現(xiàn):

#include?"Chinese.h"

void?Chinese::eating(void)
{
????cout?<"use?chopsticks?to?eat"?<endl;
}

void?Chinese::wearing(void)
{
????cout?<"wear?chinese?style"?<endl;
}

void?Chinese::drivering(void)
{
????cout?<"driver?china?car"?<endl;
}
按照上述這樣一種方法,我們繼續(xù)來實(shí)現(xiàn)Englishman類中的代碼,首先是Englishman.h中的代碼,代碼如下所示:

#ifndef?_ENGLISHMAN_H
#define?_ENGLISHMAN_H

#include?
#include?
#include?

using?namespace?std;

class?Englishman
{

public:
????void?eating(void);
????void?wearing(void);
????void?driver(void);
};

#endif
繼續(xù)看.cpp中的代碼,代碼如下所示:

#include?"Englishman.h"

void?Englishman::eating(void)
{
????cout?<"use?chopsticks?to?eat"?<endl;
}

void?Englishman::wearing(void)
{
????cout?<"wear?chinese?style"?<endl;
}

void?Englishman::drivering(void)
{
????cout?<"driver?china?car"?<endl;
}
至此,除了主函數(shù)以外的代碼就編寫完了,我們繼續(xù)來看主函數(shù)的代碼:

#include?"Englishman.h"
#include?"Chinese.h"

int?main(int?argc,?char?**argv)
{
????Englishman?e;
????Chinese?c;

????e.eating();
????c.eating();

????return?0;
}
在前面的教程中,我們就說過,如果是多文件的話,需要編寫?Makefile文件,Makefile文件代碼如下:

Human:?main.o?Chinese.o?Englishman.o?Human.o
????g ?-o?$@?$^

%.o?:?%.cpp
????g ?-c?-o?$@?$<

clean:
????rm?-f?*.o?Human?
上述代碼就不再這里贅述了,跟之前教程中的?Makefile基本是一樣的,有了Makefile之后,編譯代碼只需要使用?make命令就行了,編譯結(jié)果如下所示:

image-20210222105051169
上述代碼中,如果我們想要增添功能,比如說ChineseEnglishman都有名字,那么就可以增添設(shè)置名字和獲取名字這兩種方法,首先是?Chinese的代碼,代碼如下:

#ifndef?_CHINESE_H
#define?_CHINESE_H

#include?
#include?
#include?

using?namespace?std;

class?Chinese{
private:
????char?*name;
public:
????void?setName(char?*name);
????char?*getName(void);
????void?eating(void);
????void?wearing(void);
????void?driving(void);
????~Chinese();
};

#endif
然后是.cpp中的代碼:

#include?"Chinese.h"

void?Chinese::setName(char?*name)?
{
????this->name?=?name;
}

char?*Chinese::getName(void)?
{
????return?this->name;
}

/*其他成員函數(shù)實(shí)現(xiàn)同上,這里省略*/
寫完了?Chinese的代碼,然后是Englishman中的代碼,首先是Englishman.h中的代碼:

#ifndef?_ENGLISHMAN_H
#define?_ENGLISHMAN_H

#include?
#include?
#include?

using?namespace?std;

class?Englishman?{
private:
????char?*name;
public:
????void?setName(char?*name);
????char?*getName(void);
????void?eating(void);
????void?wearing(void);
????void?driving(void);
????~Englishman();
};

#endif
緊接著,是.cpp中的代碼:

#include?"Englishman.h"

void?Englishman::setName(char?*name)?
{
????this->name?=?name;
}

char?*Englishman::getName(void)?
{
????return?this->name;
}
以這樣的方式增添功能,確實(shí)是可行的,但是我們假設(shè)一下,如果類很多,除了中國人和英國人還有很多個(gè)國家的人,如果這些類都要增加相同的功能,這個(gè)工作量就比較大了,那要如何解決這個(gè)問題呢?這個(gè)時(shí)候,我們就可以引入一個(gè)新類Human,然后,將每個(gè)類相同的部分寫在這個(gè)類里面,其他類,諸如EnglisnmanChinese就可以從Human類中繼承而來,那這個(gè)時(shí)候,增添的操作,就只需要在?Human類中增加就好了,不需要改動(dòng)ChineseEnglishman,工作量就小了很多。我們來看?Human類的代碼實(shí)現(xiàn),首先是.h代碼的實(shí)現(xiàn):

#ifndef?_HUMAN_H
#define?_HUMAN_H

#include?
#include?
#include?

using?namespace?std;

class?Human?{
private:
????char?*name;

public:
????void?setName(char?*name);
????char?*getName(void);????
};

#endif
然后是.cpp代碼的實(shí)現(xiàn):

#include?"Human.h"

void?Human::setName(char?*name)?
{
????this->name?=?name;
}

char?*Human::getName(void)?
{
????return?this->name;
}
有了?Human類之后,我們就可以來實(shí)現(xiàn)我們所說的?EnglishmanChinese類了,代碼如下所示:

#ifndef?_ENGLISHMAN_H
#define?_ENGLISHMAN_H

#include?
#include?
#include?

#include?"Human.h"

using?namespace?std;

class?Englishman?:?public?Human?
{
public:
????void?eating(void);
????void?wearing(void);
????void?driving(void);
????~Englishman();
};

#endif
然后是Chinese的代碼:

#ifndef?_CHINESE_H
#define?_CHINESE_H

#include?
#include?
#include?

#include?"Human.h"

using?namespace?std;

class?Chinese?:?public?Human
{
public:
????void?eating(void);
????void?wearing(void);
????void?driving(void);
????~Chinese();
};

#endif
可以看到?EnglishmanChinese都是繼承自Human類,這個(gè)時(shí)候,就不需要再自己實(shí)現(xiàn)setNamegetName了。

我們繼續(xù)來完善我們的代碼,先從主函數(shù)說起,主函數(shù)代碼如下所示:

void?test_eating(Human?*h)
{
????h->eating();
}

int?main(int?argc,?char?**argv)
{
????Englishman?e;
????Chinese?c;

????Human?*?h[2]?=?{
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除( 郵箱:macysun@21ic.com )。
換一批
延伸閱讀
關(guān)閉