C++57个入门知识点_28 继承的可见性(父类成员在子类中可见性;影响因素:父类内部关键字+继承位置关键字;父亲某属性成员,变为儿子中某种属性成员;编译期检查访问权限,子类对象内存包含父类所有成员)

2023-11-19

前面我们学习了类的基本用法,并在上篇C++57个入门知识点_27 继承的概念(类的组合关系:将一个类的对象作为另外一个类的成员;类的组合关系的访问;继承的概念:A类是B的儿子;A被称为子类,B被称为父类或者A被称为派生类,B被称为基类)中介绍了继承的基本概念。本篇将会介绍继承的可见性。

总结:

  1. 前面我们学习过publicprivate关键字
  • public: 公有,其声明的成员在类域的内部和外部都可以访问;
  • private:私有,其声明的成员只能在类域的内部而不能在类域的外部访问;
  1. 保护成员(protected):保护成员除了自身或者派生类,不能在其他类使用(只有自己和儿子可以使用,其他不可以使用);
  2. 影响父类成员在子类中的可见性的关键字有两个地方:一个是父类内部的关键字,一个是继承位置的关键字
  3. 继承的可见性: 父亲某个属性的成员,通过关键字变为儿子中某种属性成员
    这个访问权限是在编译时期做的检查,实际子类的对象的内存中包含父类的所有成员
父类(CPerson) <-- 公有继承public  -- 子类(CStudent)
公有成员(public)                          公有成员(public)  
保护成员(protected)                       保护成员(protected)
私有成员(private)                         不可见
父类(CPerson) <-- 公有继承protected  -- 子类(CTeacher)
公有成员(public)                          公有成员(protected)
保护成员(protected)                       保护成员(protected)
私有成员(private)                         不可见
父类(CPerson) <-- 公有继承private  -- 子类(CTeacher)
公有成员(public)                          私有成员(private)
保护成员(protected)                       私有成员(private)
私有成员(private)                         不可见

1. protected关键字

保护成员(protected):保护成员除了自身或者派生类,不能在其他类使用(只有自己和儿子可以使用,其他不可以使用)

  • 类域外的访问属性:protectedprivate在类域外部的效果是一样的。

以下代码:CPerson类中定义了一个protected关键字的成员,在类域外对其进行访问

class CPerson
{

public:
	CPerson() {
	}

	~CPerson() {
	}

	int GetGender() {
		return m_nGender;
	}

	void SetGender(int nGender) {
		m_nGender = nGender;
	}

public:
	int m_nPublic;

protected:
	int m_nProtected;

private:
	char m_nszName[255];
	int m_nGender;
	int m_nPrivate;
};

class CStudent : public CPerson
{
public:
	CStudent() {
	}
	~CStudent() {
	}

private:
	int m_nStuID;
};

int main(int argc, char* argv[])
{
	CPerson per;
	per.m_nProtected = 1;
	return 0;
}

运行结果:显示该成员无法访问
在这里插入图片描述
对于private关键字下的int m_nPrivate也是一样的,使用CPerson per; per.m_nPrivate = 1;也是无法访问的
对于public关键字下的int m_nPublic;是可以用CPerson per; per.m_nPublic = 1;进行访问的。

  • 子类继承中的可见性:对于CPerson采用public继承的子类CStudent,其对象访问CPersonpublicprotectedprivate下的成员也是与上面结果一样。

2. 子类类域内部对父类成员的可见性

//父亲公有的都可以访问
public :
	int m_nPublic;
//父亲的家族财产给儿子继承
protected:
	int m_nProtected;
//父亲的私有财产不能给儿子继承
private:
	char m_nszName[255];
	int m_nGender;

CStudent类的内部访问CPerson的成员:

#include <iostream>

class CPerson
{

public:
	CPerson() {
	}

	~CPerson() {
	}

	int GetGender() {
		return m_nGender;
	}

	void SetGender(int nGender) {
		m_nGender = nGender;
	}

public:
	int m_nPublic;

protected:
	int m_nProtected;

private:
	char m_nszName[255];
	int m_nGender;
	int m_nPrivate;
};

class CStudent : public CPerson
{
public:
	CStudent() {
		m_nPublic = 1;
		m_nProtected = 1;
		m_nPrivate = 1;
	}
	~CStudent() {
	}

private:
	int m_nStuID;
};

int main(int argc, char* argv[])
{
	CPerson per;
	CStudent stu;
	return 0;
}

运行结果:CStudent中可以访问CPerson中的publicprotected成员,但是不能访问private
在这里插入图片描述
从上面的结果可以看到,父类中的成员对于子类是具有一定的可见性的,即父类中的不是所有成员都是可以被子类继承,有些可继承有些不可以,这些都是取决于关键字

除了CPerson内部的关键字,可以看到CStudent 继承 CPerson的地方也是可以看到关键字,class CStudent : public CPerson {...}
因此影响父类成员在子类中的可见性的关键字有两个地方,一个是父类内部的关键字,一个是继承位置的关键字

3. 父类成员在子类中的可见性

  • 关键点: 两个权限取在一起,取最严格的
  • 继承的可见性: 父亲某个属性的成员,通过关键字变为儿子中某种属性成员
    这个访问权限是在编译时期做的检查,实际子类的对象的内存中包含父类的所有成员
父类(CPerson) <-- 公有继承public  -- 子类(CStudent)
公有成员(public)                          公有成员(public)  
保护成员(protected)                       保护成员(protected)
私有成员(private)                         不可见
父类(CPerson) <-- 公有继承protected  -- 子类(CTeacher)
公有成员(public)                          公有成员(protected)
保护成员(protected)                       保护成员(protected)
私有成员(private)                         不可见
父类(CPerson) <-- 公有继承private  -- 子类(CTeacher)
公有成员(public)                          私有成员(private)
保护成员(protected)                       私有成员(private)
私有成员(private)                         不可见

以下代码中:CStudent类私有继承CPersonclass CStudent : private CPerson,查看父类成员在子类中的可见性

#include <iostream>

class CPerson
{

public:
	CPerson() {
	}

	~CPerson() {
	}

	int GetGender() {
		return m_nGender;
	}

	void SetGender(int nGender) {
		m_nGender = nGender;
	}

public:
	int m_nPublic;

protected:
	int m_nProtected;

private:
	char m_nszName[255];
	int m_nGender;
	int m_nPrivate;
};

class CStudent : private CPerson
{
public:
	CStudent() {
		m_nPublic = 1;
		m_nProtected = 1;
		//m_nPrivate = 1;
	}
	~CStudent() {
	}

private:
	int m_nStuID;
};

class CTeacher : public CPerson
{
public:
	CTeacher() {
	}
	~CTeacher() {
	}

private:
	int m_nTeaID;
};


int main(int argc, char* argv[])
{
	CStudent stu;
	stu.m_nPublic = 1;
	stu.m_nProtected = 1;
	return 0;
}

运行结果:
在这里插入图片描述

4.学习视频:C++57个入门知识点_28 继承的可见性

5.学习笔记:


#include <iostream>

//面向对象:继承
//public: 公有
//protected: 保护
//private:私有

//继承的可见性:
/*
保护成员(protected):保护成员除了自身或者派生类以外,不能在其他类使用
这个访问权限是在编译时期做的检查,实际子类的对象的内存中包含父类的所有成员
两个权限取在一起,取最严格的
父类(CPerson) <-- 公有继承public  -- 子类(CStudent)
公有成员(public)                          公有成员(public)  
保护成员(protected)                       保护成员(protected)
私有成员(private)                         不可见
父类(CPerson) <-- 公有继承protected  -- 子类(CTeacher)
公有成员(public)                          公有成员(protected)
保护成员(protected)                       保护成员(protected)
私有成员(private)                         不可见
父类(CPerson) <-- 公有继承private  -- 子类(CTeacher)
公有成员(public)                          私有成员(private)
保护成员(protected)                       私有成员(private)
私有成员(private)                         不可见
*/

class CPerson 
{

public:
	CPerson() {

	}

	~CPerson() {

	}

	int GetGender() {

		return m_nGender;
	}

	void SetGender(int nGender) {

		m_nGender = nGender;
	}
//父亲公有的都可以访问
public :
	int m_nPublic;

//父亲的家族财产给儿子继承
protected:
	int m_nProtected;

//父亲的私有财产不能给儿子继承
private:

	char m_nszName[255];
	int m_nGender;


};

//父类的继承也有三种属性
class CStudent :public CPerson
{
public:
	CStudent(){
		m_nPublic = 1;
		m_nProtected = 1;//类域内部可以访问父类的保护成员
	}

	~CStudent() {

	}

private:

	int m_nStuID;
};

//增加老师管理系统,老师的数据与行为和学生是类似的,但也有学号,老师号的不同
//如果重建一个老师类就会造成冗余,易造成错误
class CTeacher :public CPerson
{
public:
	CTeacher() {

	}

	~CTeacher() {

	}

private:

	int m_nTeaID;
};


int main(int argc,char* argv[])
{
	CPerson per;
	per.m_nPublic = 1;

	CStudent stu;

	

	return 0;
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++57个入门知识点_28 继承的可见性(父类成员在子类中可见性;影响因素:父类内部关键字+继承位置关键字;父亲某属性成员,变为儿子中某种属性成员;编译期检查访问权限,子类对象内存包含父类所有成员) 的相关文章

  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • C# xml序列化必填字段

    我需要将一些字段标记为需要写入 XML 文件 但没有成功 我有一个包含约 30 个属性的配置类 这就是为什么我不能像这样封装所有属性 public string SomeProp get return someProp set if som
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐