C++中 public和private派生类继承问题和访问权限问题
当一个子类从父类继承时,父类的所有成员成为子类的成员,此时对父类成员的访问状态由继承时使用的继承限定符决定。
1.如果子类从父类继承时使用的继承限定符是public,那么
(1)父类的public成员成为子类的public成员,允许类以外的代码访问这些成员;
(2)父类的private成员仍旧是父类的private成员,子类成员不可以访问这些成员;
(3)父类的protected成员成为子类的protected成员,只允许子类成员访问;
2.如果子类从父类继承时使用的继承限定符是private,那么
(1)父类的public成员成为子类的private成员,只允许子类成员访问;
(2)父类的private成员仍旧是父类的private成员,子类成员不可以访问这些成员;
(3)父类的protected成员成为子类的private成员,只允许子类成员访问;
3.如果子类从父类继承时使用的继承限定符是protected,那么
(1)父类的public成员成为子类的protected成员,只允许子类成员访问;
(2)父类的private成员仍旧是父类的private成员,子类成员不可以访问这些成员;
(3)父类的public成员成为子类的protected成员,只允许子类成员访问;
至于类中不同成员(public、private和protected)的访问状态就不细说了。
c++访问权限和派生继承
在基类中,public表示成员是公有的:可以由程序中任何函数访问。所以公有成员一般是成员函数,它提供了外部程序与类的接口功能,用户通过公有成员访问该类对象中的数据。
private表示成员是私有的,只允许本类的成员函数和类的友元函数访问,任何外部程序对它访问都是非法的,所有它往往是用来描述该类对象属性的一些数据成员,是类中被隐藏的部分。
protect表示成员是受保护类型的,与私有成员在一般情况下含义相同,它们的区别是,在类的继承中对产生的新类影响不同。
第一:private, public, protected 访问标号的访问范围。
private:只能由1.该类中的函数、2.其友元函数访问。
不能被任何其他访问,该类的对象也不能访问。
protected:可以被1.该类中的函数、2.其友元函数访问 3.子类的函数。
但不能被该类的对象访问。
public:可以被1.该类中的函数、2.其友元函数访问 3.子类的函数、也可以由4.该类的对象访问。
只有公有成员才能在类的外部访问。如
class A
{
private:
int a;
public:
int b;
protected:
int c;
};
A ca;
ca.a //error
ca.b // ok
ca.c //error
class B :public A
{
public:
int d;
}
B cb;
cb.b; //ok
cb.c //error。虽然c也是B的成员,但c在被继承的时候变成私有或者受保护的成员了。
注:友元函数包括3种:设为友元的普通的非成员函数;设为友元的其他类的成员函数;设为友元类中的所有成员函数。
派生类的生成过程:
class employee
{
protect:
char *name; //姓名
int individualEmpNo; //个人编号
int grade; //级别
float accumPay; //月薪总额
static int employeeNo; //本公司职员编号目前最大值
public:
employee();
~employee();
void pay(); //计算月薪函数
void promote(int); //升级函数
void displayStatus(); //显示人员信息
};
class technician:public employee
{
private:
float hourlyRate; //每小时酬金
int workHours; //当月工作时数
public:
technician(); //构造函数
void pay(); //计算月薪函数
void displayStatus(); //显示人员信息
};
分析派生新类这个过程,其继承和派生机制的主要目的是实现代码的重用和扩充。实际是经历了三个步骤:吸收基类成员、改造基类成员、添加新的成员。
1.吸收基类成员
第一步是将基类的成员全盘接收:包含了它的所有基类中除构造和析构函数之外的所有成员。
这里派生类technician继承了基类employee的除构造和析构函数以外的所有成员:
name; individualEmpNo; grade; accumPay; employeeNo;
pay(); promote(int); displayStatus();
经过派生过程,这些成员便存在于派生类之中。
2.改造基类函数
对基类成员的改造包括两个方面,
一个是基类成员的访问控制问题,主要依靠派生类声明时的继承方式来控制:
类的继承方式:public、protected和private三种访问属性。 (见上)
第二个是对基类数据或函数成员的覆盖,
如果派生类声明了一个和某个基类成员同名的新成员(如果是成员函数,则参数表也要相同,
如pay(); displayStatus(); 参数不同的情况属于重载)派生的新成员就覆盖了外层同名函数。这时,在派生类中或者通过派生类的对象直接使用成员名就只能访问到派生类中声明的同名成员,这称为同名覆盖。
3.添加新的成员
我们可以根据实际情况的需要,给派生类添加适当的数据和函数成员,来实现必要的新增功能。如technician派生类中的hourlyRate和workHours,在派生过程中,由于基类的构造函数和析构函数是不能被继承下来的,因此我们就需要在派生类重新加入新的构造函数和析构函数来实现一些特别的初始化和清理工作,例如派生类technician的构造函数technician();
第二:类的继承后方法属性变化。
特别的private,它们与派生类中新增加的private成员不同,派生类函数或是建立派生类对象的模块都无法访问到它们。)(所以只能通过在派生类中调用基类的函数去访问private属性,也可以把基类的函数用public继承下来来访问)
private继承,父类的所有方法在子类中变为private;
protected继承,父类的protected和public方法在子类中变为protected,private方法不变;
public继承,父类中的方法属性不发生改变; 原来是怎样就怎样
public一般为函数和数据,protected和private一般只为数据。
public和protected在任何方式继承的情况下,也能被子类函数调用。
如下所示:
public: protected: private:
public继承 public(含继承下来的基类函数) protected 特别的private(用派生类对象访问时)可以
被public继承下来的基类函数直接调用
protected继承 protected protected 特别的private
protected :不能被派生类对象直接调用,可间接被派生类函数和基类函数调用
特别的private:不能被派生类函数和派生类对象直接调用,(用派生类对象访问时)只能重新定义:调用基类 因为private不能被子类函数访问
private继承 private private 特别的private
private:不能被派生类对象直接调用,1.可间接被派生类函数重新定义来调用。2.基类函数调用(用派生类对象访问时)只能重新定义:调用基类 因为public和protected能被子类函数访问
上面为一次继承的情况,若有些是没区别的,当时如果再继承的话就有区别了
继承下来的访问属性分为四种:
1.区分继承与访问,特别的private为不能继承下来的,但可以访问
2.(private)成员:包括从基类继承下来的非私有成员(私有继承时),以及派生类中新增加的私有成员,在派生类内部函数都可以访问到,但派生类对象不能访问。
3.(protected)可能是新增也可能是从基类继承过来的,派生类内部成员函数可以访问,当派生类对象无法访问。
4.(public)成员:派生类成员函数和对象都能访问到
protected继承和private继承能降低访问权限。
当类的继承方式为public时,
基类的public和protected成员的访问属性在派生类中不变,而基类的private成员仍保持私有属性。
可得:派生类的其他成员函数和对象可以直接访问基类的公有成员和保护成员。
无论是派生类的成员,还是派生类的对象都无法访问基类的私有成员。
其他外部使用者只能通过派生类的对象访问继承来的公有成员
公有public继承 特别性举例:
class vehicle
{
private:
int wheels;
protected:
float weight;
public:
vehicle(int in_wheels, float in_weight)
{ wheels=in_wheels;
weight=in_weight;
}
int get_wheels(){return wheels;}
float get_weight(){return weight;}
};
class car:public vehicle
{
private:
int passenger_load;
public:
car(int in_wheels,float in_weight,int people=5):vehicle(in_wheels,in_weight)
//这里不是调用基类构造函数,而是初始化赋值列表。
{ passenger_load=people;}
int get_passengers(){return passenger_load;}
};
void main()
{
car bluebird(4,1000);
cout<<"The message of bluebird(wheels,weight,passengers):"<<endl;
cout<<bluebird.get_wheels()<<","
<<bluebird.get_weight()<<","
<<bluebird.get_passengers()<<endl;
}
car public继承verhicle后,
private:wheels;
passenger_load;// 新增的
protected:weight;
public: vehicle不存在(派生类不继承基类的构造和析构函数)
get_wheels() //可以直接访问
get_weight() //可以直接访问
car
get_passengers ;
保护protected继承
基类的public和protected成员都变为保护成员,而基类的private成员不可访问。
即基类中的保护成员只能被基类的成员函数或派生类的成员函数访问。
举例:
car protected继承verhicle后,
private:wheels;
passenger_load;// 新增的
protected:weight;
vehicle不存在(派生类不继承基类的构造和析构函数)
get_wheels()
get_weight()
public car
get_passengers ;
因为get_wheels() 和 get_weight()被派生为protected,其只能被被1.该类中的函数、2.其友元函数访问 3.子类的函数。但不能被该类的对象访问。
所以要在派生类中使用对象访问,必须做一下修改:
class car:protected vehicle
{
private:
int passenger_load;
public:
car(int in_wheels,float in_weight,int people=5):vehicle(in_wheels,in_weight)
//这里不是调用基类构造函数,而是初始化赋值列表。
{ passenger_load=people;}
int get_wheels (){return vehicle::get_wheels();} //重新定义get_wheels ()
float get_weight(){return weight;} //重新定义get_weight()
int get_passengers(){return passenger_load;}
};
这里为了保证基类的部分外部接口特征能够在派生类中也存在,就必须在派生类中重新定义同名的成员函数 get_wheels()和get_weight(),根据同名覆盖的原则,在主函数中自然调用的是派生类的函数。
如果使用私有继承: 在该例子和protected一样。
分享到:
相关推荐
根据提供的文件信息,我们可以深入探讨C++中的存储类型修饰符以及与之相关的字符转换方法,尤其是在ANSI与Unicode环境下的转换。尽管标题和描述都简短地提到了“C++存储类型修饰符”,但具体内容涉及了更具体的话题...
native 方法访问修饰符表示定义的方法在类中没有实现,而大多数情况下该方法的实现是用 C、C++ 编写的。 synchronized 方法访问修饰符 synchronized 方法访问修饰符表示多线程的支持,当一个此方法被调用时,没有...
在C++编程语言中,const是一个非常重要的修饰符,它用于声明一个变量为常量。这个修饰符的主要作用是确保变量的值在程序执行期间不会被改变,以增强程序的可读性和安全性。以下是关于const修饰符的详细知识点: 1. ...
### C++中的const限定修饰符 #### 一、引言 在C++编程语言中,`const`关键字是一个非常重要的特性,它可以帮助开发者确保某些数据或对象在其生命周期内的不变性,从而提高代码的安全性和可维护性。本文将详细介绍`...
在Java编程语言中,修饰符是用来限制或指定代码元素(如类、方法、变量)的访问权限、特性或行为的关键词。以下是对标题和描述中提及的Java修饰符及其相关知识点的详细介绍: 1. 类的访问控制修饰符: - **public*...
C++ 修饰符类型 C++ 允许在 char、int 和 double 数据类型前放置修饰符。修饰符用于改变基本类型的含义,所以它更能满足各种情境的需求。 下面列出了数据类型修饰符: signed unsigned long short 修饰符 signed、...
在protobuf中,`repeated`限定修饰符是一个非常重要的概念,用于表示一个字段可以有多个值,类似于数组或列表。本文将深入探讨`repeated`限定修饰符的使用及其相关知识点。 首先,我们需要理解protobuf的基本语法。...
本文简要总结一下C++中函数的修饰符,其中部分在实际中极少用到。 按修饰符的位置分为函数名前与函数名后两种,以下分别做介绍。 函数名前 1、返回值类型 返回值类型是C++中定义函数的必备部分,这些修饰符包括void...
C++ 允许在 char、int 和 double 数据类型前放置修饰符。修饰符用于改变基本类型的含义,所以它更能满足各种情境的需求。 下面列出了数据类型修饰符: signed unsigned long short 修饰符 signed、unsigned、...
7. **native**:原生修饰符,表示方法的实现是用其他语言(如C或C++)完成的,通过JNI(Java Native Interface)进行调用。 在IntelliJ IDEA这样的集成开发环境中,创建JavaModifierDemo项目可以帮助我们实践这些...
Java是一种面向对象的编程语言,其中修饰符和访问修饰符是控制代码访问权限和行为的重要元素。本篇文章将详细介绍Java中的各种修饰符和访问修饰符。 1. **类的访问修饰符** - `public`:任何类都可以访问声明为`...
### Java修饰符深入解析 #### 引言 Java作为一种广泛使用的面向对象编程语言,其丰富的修饰符机制为程序设计提供了灵活性和控制力。本文旨在全面剖析Java中的修饰符,包括它们的特点、用法以及如何在不同场景下...
面向对象编程语言中,诸如Java等,通过不同的访问修饰符来控制类成员(如属性、方法)的可见性和可访问性。这些修饰符包括`public`、`private`、`protected`以及`final`和`abstract`等。下面将详细解释这些关键字的...
- `native`: 原生修饰符,表示方法的实现是在其他语言(如C++)中,Java中只有方法声明。 - `strictfp`: 严格浮点运算修饰符,确保浮点计算在所有平台上的一致性。默认情况下,浮点计算可能因平台差异而略有不同。...
在C++语言中,extern、volatile、const、static等修饰符都是非常重要的,它们可以影响变量的存储方式、生命周期和访问权限等。本文将详细介绍这些修饰符的用法和特点。 一、const修饰符 const修饰符用于声明常量,...
4. **本地修饰符(native)**:native用于声明方法的实现是在Java虚拟机之外的,通常是由C或C++编写的,通过Java Native Interface (JNI)实现。 了解这些修饰符的用法和限制,对于编写高效、安全的Java代码至关重要...
Java修饰符是编程中至关重要的概念,它们用来控制代码的可见性和行为。下面是对Java修饰符的详细总结: 1. **类(class)可见性修饰符**: - `public`:类对所有类都是可见的,无论是否在同一包内,可以被导入。 ...
从给定的文件信息来看,我们深入探讨了Java语言中重要的修饰符概念,这些修饰符在编程中扮演着关键角色,它们控制着类、方法、属性等的可见性、行为和生命周期。以下是对这些核心知识点的详细解析: ### 1. Java...