C++奇淫技巧,程序员为啥天天学继承与派生,真的有这么难吗

1. 继承与派生

1.1继承与派生的概念

在C++中,可重用性是通过继承这一机制来实现的。所谓继承,就是在一个已存在的类的基础上建立一个新的类。已存在的类称为基类,新建立的类成为派生类。(与对象的复制做区别)一个新类从已有的类那里获得其已有特性,这种现象称为类的继承。

派生类继承了基类的所有数据成员和成员函数,并可以对成员作必要的增加或调整。

创一个小群,供大家学习交流聊天

如果有对学C++方面有什么疑惑问题的,或者有什么想说的想聊的大家可以一起交流学习一起进步呀。

也希望大家对学C++能够持之以恒

C++爱好群,

如果你想要学好C++最好加入一个组织,这样大家学习的话就比较方便,还能够共同交流和分享资料,给你推荐一个学习的组织:快乐学习C++组织 可以点击组织二字,可以直达


单继承:一个派生类只从一个基类派生。

多重继承:一个派生类可以从多个基类派生。

基类和派生类的关系:派生类是基类的具体化,而基类则是派生类的抽象。

1.2 派生类的声明方式

声明派生类的一般形式:

class 派生类名: 集成方式 积累名

{

派生类新增加的成员;

}

Eg:假设已经声明了一个基类Student

class Student1: public Student //声明基类是Student,集成方式是public

{

public:

void display_1() //新增加的成员函数

{

cout<<”age:”<<age<<endl;

cout<<”address:”<<addr<<endl;

}

private:

int age; //新增加的数据成员

string addr;

};

继承方式包括:public公用的,private私有的和protected受保护的。C++默认为私有继承。派生类会接收基类的所有成员,无法选择。但是可以改变积累成员在派生类中的访问属性。也可以通过同名覆盖来使新成员取代基类成员。

1.3 派生类成员的访问属性

不管是何种继承方式,基类的私有成员只有基类的成员函数才可以引用,派生类的成员函数是无法引用的。即基类的私有成员是不可见的,它在被派生类继承后变为不可访问成员。

不能通过派生类的对象引用从私有基类继承过来的任何成员。派生类的成员函数不能访问私有基类的私有成员,但可以访问私有基类的公用成员。如何调用私有基类的公用成员函数如下:

void Student::display_1()//输出学号、姓名、分数、年纪和地址

{

display();//基类中的公用成员函数,目的是输出学号、姓名和分数

cout<<”age:”<<age<<endl;

cout<<”address:”<<addr<<endl;

}

int main()

{

Student stud1;

stud1.display();//在main中调用派生类中的公用成员函数

return 0;

}

回顾:保护成员不能被类外访问,类似于私有成员。但有一点与私有成员不同,保护成员可以被派生类的成员函数引用!如果希望在派生类中可以访问基类的“私有”成员,则应当把它们声明为保护成员。

在派生类中引用保护成员

#include<iostream>

#include<string>

using namespace std;

class Student //声明基类

{

public:

void display();//基类共用成员函数

protected:

int num;//基类保护成员

string name;

char sex;

};

void Student::display()//定义基类成员函数

{

cout<<”num:”<<num<<endl;

cout<<”name:”<<name<<endl;

cout<<”sex:”<<sex<<endl;

}

class Student1: protected Student //用protected方式声明派生类

{

public:

void display1();//声明派生类共用成员函数

private:

int age;//派生类私有数据成员

string addr;

};

void Student1::display1()//定义派生类共用成员函数

{

display();

cout<<”age:”<<age<<endl;

cout<<”address:”<<addr<<endl;

}

int main()

{

Student1 stud1;

stud1.display();//合法,stud1是派生类中的共用成员函数

stud1.num=10023;//错误,外界不能访问派生类的保护成员

return 0;

}

1.4 派生类的构造函数与析构函数

构造函数的主要作用是对数据成员进行初始化,且基类的构造函数是不能继承的。对继承过来的基类成员的初始化工作主要由派生类的构造函数承担。

一、简单的派生类的构造函数

简单的派生类只有一个基类且只有一级派生,在派生类的数据称成员中不包含基类的子对象。派生类构造函数首行的写法格式:

派生类构造函数名 (总参数列表): 基类构造函数名(参数列表)

{派生类中新增数据成员初始化语句}

Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s)

例 1.10.2简单的派生类的构造函数

#include<iostream>

#include<string>

using namespace std;

class Student //声明基类

public:

Student(int n,string nam,char s):num(n),name(nam),sex(s){}//基类构造函数

~Student(){} //基类析构函数

protected:

int num;

string name;

char sex;

};

class Student1: public Student //声明派生类Student1

{

public:

Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s)

//派生类构造函数

{

age=a;在函数体中仅对派生类新增的数据成员进行初始化

addr=ad;

}

void show();

private:

int age;

string addr;

};

void Student1::show()

{

cout<<”num:”<<num<<endl;

cout<<”name:”<<name<<endl;

cout<<”sex:”<<sex<<endl;

cout<<”age:”<<age<<endl;

cout<<address:”<<addr<<endl;

}

int main()

{

Student1 stud1(10010,”Wang li”,’f’,19,”115 Beijing Road, Shanghai”);

Student1 stud2(10011.”Zhang fun”,’m’,21,”213 Shanghai Road, Beijing”);

stud1.show();

stud2.show();

return 0;

}

实参首先传给派生类构造函数的形参,然后派生类构造函数再将前面几个传递给基类构造函数的形参。上例的具体过程见图1.5。

图 1.5 参数传递过程

在类内声明派生类的构造函数,然后在类外定义派生类的构造函数

class Student1: protected Student

{

public:

Student1(int n,string nam,char s,int a,string ad);

};

Student1::Student1(int n,string nam,char s,int a,string ad):Student(n,nam,s)

//定义时才给出基类构造函数名及其参数列表,声明时不给出

{

age=a;

addr=ad;

}

二、有子对象的派生类构造函数

类的数据成员还可包含对象,称为子对象。

格式:

派生类构造函数名(总参数列表):基类构造函数名(参数列表),子对象名(参数列表)

{派生类中新增加的数据成员初始化语句}

Student1(intn,string nam,int n1,string nam1,int a,string ad): Student(n,nam),monitor(n1,nam1)

执行派生类构造函数的顺序:

① 调用基类构造函数,对基类数据成员初始化。

② 调用子对象构造函数,对子对象数据成员初始化。

③ 在执行派生类构造函数本身,对派生类数据成员初始化。

在派生时,派生类是不能够继承基类的析构函数的,也需要通过派生类的析构函数去调用基类的析构函数。


1.5 多重继承

一个派生类有2个或多个基类,派生类从2个或多个基类中继承所需的属性。如果已经声明了类A和类B,则可以声明多重继承的派生类C:

class C: public A, protected B

{类C新增加的成员};

一、多重继承派生类的构造函数

类似于单继承,但是在初始表中包含多个基类构造函数。多重继承派生类构造函数首行的写法格式:

派生类构造函数名(总参数列表):基类1构造函数(参数列表),基类2构造函数(参数列表)…

{派生类中新增数据成员初始化语句}

例 1.10.3声明一个教师类和一个学生类,然后用多重继承的方式声明一个研究生类。教师类包括数据成员name,age和title(职称)。学生类包括数据成员name1,sex和score。

#include<iostream>

#include<string>

using namespace std;

class Teacher //声明类Teacher

{

public:

Teacher(string nam,int a,string t):name(nam),age(a),title(t){}//构造函数初始化表

void display();//输出教师的数据

protected:

string name;

int age;

string title;

};

void Teacher::display()

{

cout<<”name:”<<name<<endl;

cout<<”age:”<<age<<endl;

cout<<”title:”<<title<<endl;

}

class Student //声明类Student

{

public:

Student(char nam[],char s,float sco)

{

strcpy(name1,nam);

sex=s;

score=sco;

}

void display1();

protected:

string name1;

char sex;

float score;

};

void Student::display1()

{

cout<<”name:”<<name1<<endl;

cout<<”sex:”<<sex<<endl;

cout<<”score:”<<score<<endl;

}

class Graduate: public Teacher,public Student //声明多重继承的派生类Graduate

{

public:

Graduate(string nam,int a,char s,string t,float sco,float w): Teacher(nam,a,t), Student (nam, s, sco)

{wage=w;}

//多重继承的派生类的构造函数

void show();//输出研究生有关数据

private:

float wage;//工资

};

void Graduate::show()

{

cout<<”name:”<<name<<endl;

cout<<”age:”<<age<<endl;

cout<<”sex:”<<sex<<endl;

cout<<”score:”<<score<<endl;

cout<<”title:”<<title<<endl;

cout<<”wages:”<<wage<<endl;

}

int main()

{

Graduate grad1(“Wang li”,24,’f’,”assistant”,89.5,1234.5);

grad1.show();

return 0;

}

二、多重继承引起的二义性问题

继承的成员同名会产生二义性问题。

同名覆盖:基类的同名成员在派生类中被屏蔽,成为不可见的,或者说,派生类新增加的同名成员覆盖了基类中的同名成员。解决这种情况需要虚函数。

如果类A和类B都是从一个基类派生的,情况如下图1.6:

图 1.6 二义性问题的一种情况

解决这种情况需要用到虚基类。

1.6 虚基类

一、虚基类的声明

由图1.6可知,如果一个派生类有多个直接接类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接共同基类数据成员的多份同名成员。为避免二义性,必须在派生类对象名后增加直接基类名,如c1.A::display()。C++提供虚基类的方法,使得在继承间接共同基类时只保留一份成员。

声明虚基类的一般形式:

class 派生类名: virtual 继承方式 基类名

Eg:

class A //声明基类A

{……};

class B: virtual public A //声明类B是类A的共用派生类,A是B的虚基类

{……};

虚基类不是在声明基类时声明的,而是在声明派生类时声明的。virtual关键字不仅可以声明虚基类,也用于声明虚函数。在声明派生类时,需要把virtual加到相应的继承方式前面。经过这样的声明后,当基类通过多条派生路径被一个派生类级城市,基类成员只保留一次。如图1.7。

图 1.7 虚基类的情况

为了保证虚基类在派生类中只被继承一次,应当在该基类的所有直接派生类中声明为虚基类,否则仍会出现对基类的多次继承。

二、虚基类的初始化

由于虚基类在派生类中只有一份数据成员,所以这份数据成员的初始化必须由派生类直接给出。在最后的派生类中,不仅需要负责对直接基类进行初始化,也需要对虚基类进行初始化。

例 1.10.4 在例1.10.3的基础上,在教师类和学生类之上添加一个共同的基类Person。

#include<iostream>

#include<string>

using namespace std;

class Person //声明公共基类Peroson

{

public:

Person(string nam,char s,int a):name(name),sex(s),age(a){}//构造函数

protected:

string name;

char sex;

int age;

};

class Teacher:virtual public Teacher

//声明Person的直接派生类Teacher,且声明Person为公用继承的虚基类

{

public:

Teacher(string nam,char s,int a,string t):Person(nam,s,a)//构造函数

{title=t;}

protected:

string title;

};

class Student:virtual public Person

//声明Person的直接继承类Student,且声明Person为公用继承的虚基类

{

public:

Student(string nam,char s,int a,float sco):Person(nam,s,a)

{score=sco;}

protected:

float score;

};

class Graduate: public Teacher,public Student //声明多重继承的派生类Graduate

{

public:

Graduate(string nam,char s,int a,string t,float sco,float w):Person(nam,s,a),Teacher(name, s,a,t),Student(nam,s,a,sco) //在派生类中的构造函数,对直接基类和间接基类进行初始化

{wage=w;}

void show();

private:

float wage;

};

void Graduate::show()

{

cout<<”name:”<<name<<endl;

cout<<”age:”<<age<<endl;

cout<<”sex:”<<sex<<endl;

cout<<”score:”<<score<<endl;

cout<<”title:”<<title<<endl;

cout<<”wages:”<<wage<<endl;

}

int main()

{

Graduate grad1(“Wang li”,’f’,24,”assistant”,89.5,1234.5);

grad1.show();

return 0;

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容