- 五、组合与继承
- 1、回顾标准io流
- 例22、在C++中,io流表示
- 2、组合
- 例23、组合
- 3、继承
- 例24、继承(1)
- 组合和继承的区分:
- 例25、继承(2)
在C语言中,键盘输入打印信息如下
#includeint main() { printf("input:");fflush(stdout); char buf[100]; fgets(buf); printf("%sn",buf); }
运行结果
@ubuntu:/mnt/hgfs/ub2$ gcc cin_cout1.c
cin_cout1.c: In function ‘main’:
cin_cout1.c:8:5: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
gets(buf);
^~~~
fgets
/tmp/ccOXH43A.o: In function `main':
cin_cout1.c:(.text+0x44): warning: the `gets' function is dangerous and should not be used.
@ubuntu:/mnt/hgfs/ub2$ ./a.out
input:dskfjsdoj
dskfjsdoj
@ubuntu:/mnt/hgfs/ub2$
例22、在C++中,io流表示
#include#include using namespace std; int main() { // printf("input:");fflush(stdout); cout<<"input:"; char buf[100]; // gets(buf); cin>>buf; // printf("%sn",buf); cout< 运行结果
@ubuntu:/mnt/hgfs/ub2$ g++ cin_cout2.cpp @ubuntu:/mnt/hgfs/ub2$ ./a.out input:soadjaofaoh soadjaofaoh @ubuntu:/mnt/hgfs/ub2$当然,除此之外还可以直接打印数字,以及其对应的进制数
#include#include using namespace std; int main() { // printf("input:");fflush(stdout); cout<<"input:"; char buf[100]; // gets(buf); cin>>buf; // printf("%sn",buf); cout< 运行结果
@ubuntu:/mnt/hgfs/ub2$ g++ cin_cout3.cpp @ubuntu:/mnt/hgfs/ub2$ ./a.out input:dsofhsighshgo dsofhsighshgo 10 a @ubuntu:/mnt/hgfs/ub2$2、组合假如现在需要做个学生管理系统类的应用,然后想起之前做过一个有尾部追加功能的类,在这里有机会用上,于是,组合就派上了用场。
比如说,之前做的尾部追加功能数组类叫ARR,现在想用在目前的学生管理系统类stuma里,实现如下
例23、组合arr.cpp
#include "arr.h" #include//ARR类的两个成员函数,addtail和show void ARR::addtail(int data) { this->data[tail++] = data; } void ARR::show(void) { int i = 0; for(;i arr.h
#ifndef _ARR_ #define _ARR_ class ARR{ public: ARR():tail(0){ } void addtail(int data); void show(void); private: int data[100]; int tail; }; #endifmain.cpp
#include "arr.h" class Stuma{ public: Stuma(){ } ~Stuma() { } void savescore(int score) { scorearr.addtail(score); } void showscore(void) { scorearr.show(); } private: ARR scorearr; }; int main() { Stuma mmm; mmm.savescore(23); mmm.savescore(44); mmm.savescore(55); mmm.savescore(23); mmm.showscore(); }运行结果
@ubuntu:/mnt/hgfs/ub2/ARR1$ g++ *.cpp @ubuntu:/mnt/hgfs/ub2/ARR1$ ./a.out 23, 44, 55, 23, @ubuntu:/mnt/hgfs/ub2/ARR1$上例的addtail()本来是属于ARR类的,让它组合其它功能实现一起(本例没组合其它功能实现)进行再次封装,得到属于stuma类的savescore(),同理,ARR类的show()经过再次封装得到stuma类的showscore()。示意图如下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u7dzRkSj-1655908744452)(D:Typora_pic1655434361516.png)]
组合的妙处在于化他人之功能为己用,很多时候我们会接触这种情况:开发东西需要用到A、B、C、D等功能,然后你手头有关于A、B、C、D功能实现的大佬的资源(网上开源、公司提供等等),于是就可以使用组合把这些大佬的功能整合为己用。否则,你就得自己去实现ABCD的功能,这样不但耗时耗精力,而且很有可能出现各种各样bug,质量得不到保证。(毕竟大佬的代码是经过千锤百炼得出的精华)
3、继承 例24、继承(1)首先,简单实现打印x到屏幕
#includeusing namespace std; class A{ public: A(){ } ~A(){ } void showx() { cout<<"xxxxxxxxxxxxxxx"< 执行结果
@ubuntu:/mnt/hgfs/ub2$ g++ base1_1.cpp @ubuntu:/mnt/hgfs/ub2$ ./a.out xxxxxxxxxxxxxxx @ubuntu:/mnt/hgfs/ub2$现在我想打印y而不是x,即a.showy(),很明显是不行的,于是就需要对show功能进行升级。
有两种情况:
- 能拿到源代码
这种情况就简单了,直接在对应类(class A)里添加对应功能
void showy() { cout<<"yyyyyyyyyyyyyyy"<
- 拿不到源代码
但很多时候拿不到别人源码,又想用人家的类似功能,于是就需要继承(派生)。
表示形式如下
class AX:public A{ };AX是A的派生类,虽然拿不到别人的类A,但可以对类A派生出自己的类AX,然后类AX就继承了类A的功能。接下来只需要对类AX进行自己的编程操作添加需要的功能,便可以不仅实现自己功能而且还拥有所继承的类A的功能。
案例如下
#includeusing namespace std; class A{ public: A(){ } ~A(){ } void showx() { cout<<"xxxxxxxxxxxxxxx"< 执行结果
@ubuntu:/mnt/hgfs/ub2$ g++ base1_2.cpp @ubuntu:/mnt/hgfs/ub2$ ./a.out xxxxxxxxxxxxxxx yyyyyyyyyyyyyyy @ubuntu:/mnt/hgfs/ub2$可以发现,类AX不仅有了自己的打印y功能,而且继承了类A的打印x功能(也可以说成是类A派生打印x的功能给了AX)。
组合和继承的区分:组合是把优秀的功能实现进行整合作为自己的功能;而继承(派生)是在优秀的功能实现基础上添加自己的功能,起站在巨人的肩膀上的效率。
举个例子:假如我需求是一根黑线,那么组合就是把各黑点紧密排成一队形成黑线;假如我需要一根红线,那么继承就是以别人的线为基础,然后染成红色。
例25、继承(2)现在再举个复杂点的例子:
回顾例23,如下
arr.cpp
#include "arr.h" #include//ARR类的两个成员函数,addtail和show void ARR::addtail(int data) { this->data[tail++] = data; } void ARR::show(void) { int i = 0; for(;i arr.h
#ifndef _ARR_ #define _ARR_ class ARR{ public: ARR():tail(0){ } void addtail(int data); void show(void); private: int data[100]; int tail; }; #endifmain.cpp
#include "arr.h" class Stuma{ public: Stuma(){ } ~Stuma() { } void savescore(int score) { scorearr.addtail(score); } void showscore(void) { scorearr.show(); } private: ARR scorearr; }; int main() { Stuma mmm; mmm.savescore(23); mmm.savescore(44); mmm.savescore(55); mmm.savescore(23); mmm.showscore(); }这是模拟学生管理系统的功能。现在说要在原基础上增加求平均的功能,如果是一般情况,就去arr.cpp和arr.h添加功能,类似addtail()和show()那样。如下
arr.cpp
#include "arr.h" #includevoid ARR::addtail(int data) { this->data[tail++] = data; } void ARR::show(void) { int i = 0; for(;i arr.h
#ifndef _ARR_ #define _ARR_ class ARR{ public: ARR():tail(0){ } void addtail(int data); void show(void); int ever(void); private: int data[100]; int tail; }; #endifmain.cpp
#include "arr.h" #includeusing namespace std; class Stuma{ public: Stuma(){ } ~Stuma() { } void savescore(int score) { scorearr.addtail(score); } int everscore(void) { return scorearr.ever(); } void showscore(void) { scorearr.show(); } private: ARR scorearr; }; int main() { Stuma mmm; mmm.savescore(23); mmm.savescore(44); mmm.savescore(55); mmm.savescore(23); mmm.showscore(); cout< 执行结果:
@ubuntu:/mnt/hgfs/ub2/ARR2_1$ g++ *.cpp @ubuntu:/mnt/hgfs/ub2/ARR2_1$ ./a.out 23, 44, 55, 23, 36 @ubuntu:/mnt/hgfs/ub2/ARR2_1$然而,很多时候你拿不到别人的arr文件,这样的话就需要用继承来实现。先以ARR为基础派生出自己的类ARRX,然后在ARRX里添加功能,接着再把ARRX组合到类stuma。如下
arr.cpp
#include "arr.h" #includevoid ARR::addtail(int data) { this->data[tail++] = data; } void ARR::show(void) { int i = 0; for(;i arr.h
#ifndef _ARR_ #define _ARR_ class ARR{ public: ARR():tail(0){ } void addtail(int data); void show(void); private: int data[100]; int tail; }; #endifmain.cpp
#include "arr.h" #includeusing namespace std; class ARRX:public ARR{ public: int ever(void) { int i = 0; int sum = 0; for(;i 执行结果报错
wu@ubuntu:/mnt/hgfs/ub2/level14/2day/ARR2_2$ g++ *.cpp main.cpp: In member function ‘int ARRX::ever()’: main.cpp:12:10: error: ‘int ARR::tail’ is private within this context for(;i这是因为public继承方式中,基类的所有private成员在派生类中不可访问
class ARRX:public ARR//ARRX是派生类,ARR是基类,public表示继承方式关于继承方式,下图所示
所以出错原因在于私有成员(private)被限制,除此之外还有个错误是:类ARR派生成ARRX后,组合的应该是ARRX而不是ARR,见错误提示
main.cpp: In member function ‘int Stuma::everscore()’: main.cpp:32:19: error: ‘class ARR’ has no member named ‘ever’ return scorearr.ever();所以把arr.h的私有成员公开出来,然后main.cpp的类stuma私有成员改为ARRX的,如下
arr.cpp
#include "arr.h" #includevoid ARR::addtail(int data) { this->data[tail++] = data; } void ARR::show(void) { int i = 0; for(;i arr.h
#ifndef _ARR_ #define _ARR_ class ARR{ public: ARR():tail(0){ } void addtail(int data); void show(void); //private: int data[100]; int tail; }; #endifmain.cpp
#include "arr.h" #includeusing namespace std; class ARRX:public ARR{ public: int ever(void) { int i = 0; int sum = 0; for(;i 执行结果:
@ubuntu:/mnt/hgfs/ub2/ARR2_2$ g++ *.cpp @ubuntu:/mnt/hgfs/ub2/ARR2_2$ ./a.out 23, 44, 55, 23, 36 @ubuntu:/mnt/hgfs/ub2/ARR2_2$



