9.1 基类与派生类
被继承的类称为父类或基类,继承的类称为子类或派生类。
“子类”和“父类”通常放在一起称呼,“基类”和“派生类”通常放在一起称呼。
派生类除了拥有基类的成员,还可以定义自己的新成员,以增强类的功能。
使用继承的场景:
- 创建的新类只是比原有类多出若干成员变量或成员函数时,可以使用继承,这样会减少代码量,新类也会拥有基类的所有功能。
- 需要创建多个类,这类有相似的成员变量或成员函数时,也可以使用继承。
提取共同成员,定义为基类,然后从基类继承,可以节省代码,方便后续修改。
#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;
}
继承的基本格式
class 派生类名:[继承方式] 基类名{
派生类新增加的成员
};
9.2 继承方式
继承方式限定了基类成员在派生类中的访问权限,包括 public(公有的)、private(私有的)和 protected(受保护的)。如果不写,默认为 private。protected 成员和 private 成员类似,也不能通过对象访问。但是当存在继承关系时,基类中的 protected 成员可以在派生类中使用,而基类中的 private 成员不能在派生类中使用public、protected、private 指定继承方式。
不同的继承方式会影响基类成员在派生类中的访问权限。
- public继承方式
基类中所有 public 成员在派生类中为 public 属性;
基类中所有 protected 成员在派生类中为 protected 属性;
基类中所有 private 成员在派生类中不能使用。 - protected继承方式
基类中的所有 public 成员在派生类中为 protected 属性;
基类中的所有 protected 成员在派生类中为 protected 属性;
基类中的所有 private 成员在派生类中不能使用。 - private继承方式
基类中的所有 public 成员在派生类中均为 private 属性;
基类中的所有 protected 成员在派生类中均为 private 属性;
基类中的所有 private 成员在派生类中不能使用。
注意:
1、基类成员在派生类中的访问权限不得高于继承方式中指定的权限。
2、不管继承方式如何,基类中的 private 成员在派生类中始终不能使用(不能在派生类的成员函数中访问或调用)。
3、如果想基类的成员能够被派生类继承并且使用,那么这些成员只能声明为 public 或 protected;只有那些不希望在派生类中使用的成员才声明为 private。
4、如果想基类的成员既不向外暴露(不能通过对象访问),还能在派生类中使用,那么只能声明为 protected。
5、private 和 protected 继承方式会改变基类成员在派生类中的访问权限,导致继承关系复杂,所以实际开发中我们一般使用 public
6、基类的 private 成员不能在派生类中使用,并没有说基类的 private 成员不能被继承。
实际上,基类的 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,导致无法使用罢了。private 成员的这种特性,能够很好的对派生类隐藏基类的实现,以体现面向对象的封装性。
···
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;
}
···
注意:
在派生类中访问基类 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)