9. C++ 继承 基类、派生类、访问权限

9.1 基类与派生类

被继承的类称为父类或基类,继承的类称为子类或派生类。
“子类”和“父类”通常放在一起称呼,“基类”和“派生类”通常放在一起称呼。
派生类除了拥有基类的成员,还可以定义自己的新成员,以增强类的功能。

使用继承的场景:

  1. 创建的新类只是比原有类多出若干成员变量或成员函数时,可以使用继承,这样会减少代码量,新类也会拥有基类的所有功能。
  2. 需要创建多个类,这类有相似的成员变量或成员函数时,也可以使用继承。
    提取共同成员,定义为基类,然后从基类继承,可以节省代码,方便后续修改。
#include<iostream>
using namespace std;

//基类 Pelple
class Person{
public:
    void setname(char *name);
    void setage(int age);
    char *getname();
    int getage();
private:
    char *name;
    int age;
};
void Person::setname(char *name){ this->name = name; }
void Person::setage(int age){ this->age = age; }
char* Person::getname(){ return this->name; }
int Person::getage(){ return this->age;}

//派生类 Student
class Student: public Person{
public:
    void setscore(float score);
    float getscore();
private:
    float score;
};

void Student::setscore(float score){ this->score = score; }
float Student::getscore(){ return this->score; }

int main(){
    Student stu;
    stu.setname("豆豆");
    stu.setage(15);
    stu.setscore(80.0);
    cout<<stu.getname()<<"的年龄是 "<<stu.getage()<<",成绩是 "<<stu.getscore()<<endl;
    return 0;
}
image.png

继承的基本格式

class 派生类名:[继承方式] 基类名{
    派生类新增加的成员
};

9.2 继承方式

继承方式限定了基类成员在派生类中的访问权限,包括 public(公有的)、private(私有的)和 protected(受保护的)。如果不写,默认为 private。protected 成员和 private 成员类似,也不能通过对象访问。但是当存在继承关系时,基类中的 protected 成员可以在派生类中使用,而基类中的 private 成员不能在派生类中使用public、protected、private 指定继承方式。

不同的继承方式会影响基类成员在派生类中的访问权限。

  1. public继承方式
    基类中所有 public 成员在派生类中为 public 属性;
    基类中所有 protected 成员在派生类中为 protected 属性;
    基类中所有 private 成员在派生类中不能使用。
  2. protected继承方式
    基类中的所有 public 成员在派生类中为 protected 属性;
    基类中的所有 protected 成员在派生类中为 protected 属性;
    基类中的所有 private 成员在派生类中不能使用。
  3. private继承方式
    基类中的所有 public 成员在派生类中均为 private 属性;
    基类中的所有 protected 成员在派生类中均为 private 属性;
    基类中的所有 private 成员在派生类中不能使用。

注意:
1、基类成员在派生类中的访问权限不得高于继承方式中指定的权限。
2、不管继承方式如何,基类中的 private 成员在派生类中始终不能使用(不能在派生类的成员函数中访问或调用)。
3、如果想基类的成员能够被派生类继承并且使用,那么这些成员只能声明为 public 或 protected;只有那些不希望在派生类中使用的成员才声明为 private。
4、如果想基类的成员既不向外暴露(不能通过对象访问),还能在派生类中使用,那么只能声明为 protected。
5、private 和 protected 继承方式会改变基类成员在派生类中的访问权限,导致继承关系复杂,所以实际开发中我们一般使用 public
6、基类的 private 成员不能在派生类中使用,并没有说基类的 private 成员不能被继承。

实际上,基类的 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,导致无法使用罢了。private 成员的这种特性,能够很好的对派生类隐藏基类的实现,以体现面向对象的封装性。

image.png

···

include<iostream>

using namespace std;

//基类Person
class Person{
public:
void setname(char *name);
void setage(int age);
void sethobby(char *hobby);
char *gethobby();
protected:
char *name;
int age;
private:
char *hobby;
};
void Person::setname(char *name){ this->name = name; }
void Person::setage(int age){ this->age = age; }
void Person::sethobby(char *hobby){ this->hobby = hobby; }
char *Person::gethobby(){ return hobby; }

//派生类Student学生
class Student: public Person{
public:
void setscore(float score);
protected:
float score;
};
void Student::setscore(float score){ this->score = score; }

//派生类Pupil未成年人
class Pupil: public Student{
public:
void setranking(int ranking);
void display();
private:
int ranking;//排名
};
void Pupil::setranking(int ranking){ this->ranking = ranking; }
void Pupil::display(){
cout<<this->name<<"的年龄是"<<this->age<<",考试成绩为"<<this->score<<"分,班级排名第"<<this->ranking<<",TA喜欢"<<gethobby()<<"。"<<endl;
}

int main(){
Pupil pup;
pup.setname("哈哈");
pup.setage(15);
pup.setscore(90.0);
pup.setranking(4);
pup.sethobby("篮球");
pup.display();
return 0;
}
···


image.png

注意:
在派生类中访问基类 private 成员的唯一方法就是借助基类的public的set和get成员函数,
如果基类没有非 private 成员函数,那么该成员在派生类中将无法访问。

改变访问权限
使用 using 关键字可以改变基类成员在派生类中的访问权限。
注意:using 只能改变基类中 public 和 protected 成员的访问权限,不能改变 private 成员的访问权限,
因为基类中 private 成员在派生类中是不可见的,根本不能使用,
所以基类中的 private 成员在派生类中无论如何都不能访问。

···

include<iostream>

using namespace std;

//基类Person
class Person {
public:
void show();
protected:
char *name;
int age;
};
void Person::show() {
cout << this->name << "的年龄是" << this->age << endl;
}

//派生类Student
class Student : public Person {
public:
void learning();
public:
using Person::name; //将protected改为public
using Person::age; //将protected改为public
float score;
private:
using Person::show; //将public改为private
};

void Student::learning() {
cout << "我是" << this->name << ",今年" << this->age << "岁,这次考了" << this->score << "分!" << endl;
}

int main() {
Student stu;
stu.name = "小明";
stu.age = 16;
stu.score = 99.5f;
stu.show(); //compile error
stu.learning();
return 0;
}

![image.png](https://upload-images.jianshu.io/upload_images/16823531-78cdc0542df07346.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

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