1. 三种继承方式
在C++中,继承是一种重要的面向对象编程机制,允许子类继承父类的成员(包括成员变量和成员函数)。根据不同的继承方式,子类对父类成员的访问权限会有所不同。
Public继承:
父类访问权限 | 继承方式 | 子类访问权限 |
---|
public | public | public |
protected | public | protected |
private | public | 不可见(继承了,但无法访问) |
Protected继承:
父类访问权限 | 继承方式 | 子类访问权限 |
---|
public | protected | protected |
protected | protected | protected |
private | protected | 不可见(继承了,但无法访问) |
Private继承:
父类访问权限 | 继承方式 | 子类访问权限 |
---|
public | private | private |
protected | private | private |
private | private | 不可见(继承了,但无法访问) |
子类内部访问父类成员的权限取决于父类成员本身的访问权限和继承方式中权限较小的一个。开发中最常用的继承方式是public继承,因为这种方式保留了父类原有的成员访问权限。需要注意的是,访问权限不会影响对象的内存布局。
2. 函数遮蔽
当子类中定义了一个与父类同名的函数时,无论父类中有多少个同名函数,子类都无法直接访问这些同名函数。如果需要调用父类中的同名函数,可以通过以下两种方法实现:
(1) 在子类的成员函数中,使用父类名::函数名
来显式调用父类的成员函数。
#include
using namespace std;
class Person {
public:
void run() { cout <<"Person::run()" < void run(int) { cout <<"Person::run(int)" < void run(int, int) { cout <<"Person::run(int, int)" <};
class Student : public Person {
public:
void run() { Person::run(); cout <<"Student::run()" <};
int main() {
Student stu;
stu.run();
return 0;
}
(2) 在C++11及更高版本中,可以通过using
关键字将父类的同名函数引入到子类中,使它们在子类中以重载的形式可见。
#include
using namespace std;
class Person {
public:
void run() { cout <<"Person::run()" < void run(int) { cout <<"Person::run(int)" < void run(int, int) { cout <<"Person::run(int, int)" <};
class Student : public Person {
public:
using Person::run;
void run(int) { cout <<"Student::run(int)" <};
int main() {
Student stu;
stu.run();
stu.run(10); // 如果同名同参,则仍调用子类自己的
stu.run(10, 20);
return 0;
}