IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 【C++】继承 -> 正文阅读

[系统运维]【C++】继承

1. 简述继承

  • 继承的基本语法:
class 子类 : 继承权限 父类
  • 示例:
class Animal {
public :
    string name() { return this->__name; }
private :
    string __name;
};

class Cat : public Animal {

};
  • 子类继承了父类的什么呢?
  1. 继承父类的所有成员属性和方法,涉及到相关的访问控制权限
  2. 子类拥有父类成员,但是不代表子类能访问这些成员

2.子类的访问权限

继承权限究竟意味着什么?子类能够访问到父类的哪些成员属性和成员方法?

子类之于父类是父类的类外,无论什么继承权限,在子类中都只能访问到父类的 publicprotected 权限的成员

注意:在子类外声明的子类对象属于子类类外,是否能访问子类中继承自父类的成员,就要看“对外的访问属性”。

继承权限(横)
属性在基类中的权限(竖)
publicprotectedprivate
public???
protected???
private???

表中横竖两栏的交叉点表示子类能否访问父类中该权限的成员。

子类的访问权限与继承权限无关,只能访问public和protected权限的成员

3. 对外的访问权限

假设类Base 中有个属性 a,子类Sub 继承自 Base 类,外部能否看到 Sub 类中的属性 a,取决于Base 中属性 a 的访问权限和子类Sub 继承 Base 的继承权限

“继承权限"影响类外访问子类内继承自父类的属性的"访问权限”

继承权限(横)
属性在基类中的权限(竖)
publicprotectedprivate
publicpublicprotectedprivate
protectedprotectedprotectedprivate
private???

两栏交叉位置就是子类中继承自父类的属性的对外访问权限,上表表现的就是取两个权限中权限较低的。

对 外 的 访 问 权 限 = m i n ( 子 类 继 承 权 限 , 基 类 中 属 性 的 访 问 权 限 ) 对外的访问权限 = min(子类继承权限,基类中属性的访问权限) 访=min(访)

4. 代码测试

4.1 父类对象和子类对象的大小

#include <iostream>
using namespace std;

class Animal {
public :
    Animal() = default;
    Animal(string name) : name(name) {}
    void say() {
        cout << "My name is " << name << endl;
    }
private :
    string name;
};

class Cat : public Animal {};

int main() {
    cout << sizeof(Animal) << " " << sizeof(Cat) << endl; 
    return 0;
}

运行结果:

24 24

对象的大小只和属性有关,Cat 对象和 Animal 对象大小完全相同,因为 Cat 类继承自 Animal 类,所以继承了 Animal 类中的所有属性。

4.2 不同的继承权限

1、Cat 私有继承 Animal,Tiger 公有继承 Cat

/*************************************************************************
	> File Name: Cat.cpp
	> Author: Maureen
	> Mail: Maureen@qq.com
	> Created Time: 五  1/ 7 12:39:12 2022
 ************************************************************************/

#include <iostream>
using namespace std;

class Animal {
public :
    Animal(string name = "mimi") : name(name) {}
    void say() {
        cout << "My name is " << name << endl;
    }
protected :
    string name;
};

class Cat : private Animal {
public :
    void say1() {
        cout << "miaomiaomiao, my name is " << name << endl;
    }
};

class Tiger : public Cat {
public :
    void say2() {
        cout << "houhouhou, my name is " << name << endl;
    }
};

int main() {
    cout << sizeof(Animal) << " " << sizeof(Cat) << endl;
    Cat c;
    //c.say(); //Cat私有继承Animal,say()方法对外的属性
    c.say1();
    return 0;
}

编译出错:

Cat.cpp:31:45: error: 'name' is a private member of 'Animal'
        cout << "houhouhou, my name is " << name << endl;
                                            ^
Cat.cpp:21:13: note: constrained by private inheritance here
class Cat : private Animal {
            ^~~~~~~~~~~~~~
Cat.cpp:18:12: note: member is declared here
    string name;
           ^
1 error generated.

错误原因:Cat 因为继承自 Animal,它拥有了父类的 name 属性,因为是私有继承自父类,所以 Cat 类中的 name 属性的访问权限是 private,而 Tiger 是 Cat 的子类,子类无法访问到父类的私有成员。

2、Cat 继承 Animal 的继承权限为 protected

#include <iostream>
using namespace std;

class Animal {
public :
    Animal(string name = "mimi") : name(name) {}
    void say() {
        cout << "My name is " << name << endl;
    }
protected :
    string name;
};

class Cat : protected Animal {
public :
    void say1() {
        cout << "miaomiaomiao, my name is " << name << endl;
    }
};

class Tiger : public Cat {
public :
    void say2() {
        cout << "houhouhou, my name is " << name << endl;
    }
};

int main() {
    cout << sizeof(Animal) << " " << sizeof(Cat) << endl;
    Cat c;
    //c.say(); //Cat私有继承Animal,say()方法对外的属性
    c.say1();
    return 0;
}

可成功编译,因为 name 属性无论是在 Animal 类中还是 Cat 类中对外的访问权限都是 protected,Tiger 作为 Cat 的子类,可以访问父类的 protected 属性。

3、Cat 公有继承 Animal,Tiger 公有继承 Cat

#include <iostream>
using namespace std;

class Animal {
public :
    Animal(string name = "mimi") : name(name) {}
    void say() {
        cout << "My name is " << name << endl;
    }
protected :
    string name;
};

class Cat : public Animal {
public :
    void say1() {
        cout << "miaomiaomiao, my name is " << name << endl;
    }
};

class Tiger : public Cat {
public :
    void say2() {
        cout << "houhouhou, my name is " << name << endl;
    }
};

int main() {
    cout << sizeof(Animal) << " " << sizeof(Cat) << endl;
    Cat c;
    c.say1();
	//子类对象隐式转换为父类指针 
	//小知识:子类对象的地址可以隐式转换为父类的地址,如一个中国人,那默认就是个人
    Animal *p = &c;
    p->say();
    return 0;
}

运行结果:

24 24
miaomiaomiao, my name is mimi
My name is mimi

4、修改为 protected / private 继承

/*************************************************************************
	> File Name: Cat.cpp
	> Author: Maureen 
	> Mail: Maureen@qq.com 
	> Created Time: 五  1/ 7 23:52:33 2022
 ************************************************************************/

#include <iostream>
using namespace std;

class Animal {
public :
    Animal(string name = "mimi") : name(name) {}
    void say() {
        cout << "My name is " << name << endl;
    }
    void rename(string name) {
        this->name = name;
    }
protected :
    string name;
};

class Cat : private Animal {
public :
    void say1() {
        cout << "miaomiaomiao, my name is " << name << endl;
    }
};

//class Tiger : public Cat {
//public :
//    void say2() {
//        cout << "houhouhou, my name is " << name << endl;
//    }
//};

int main() {
    cout << sizeof(Animal) << " " << sizeof(Cat) << endl;
    Cat c;
    c.say1();

    Animal *p = &c;
    p->say();
    return 0;
}

编译出错:

Cat.cpp:43:17: error: cannot cast 'Cat' to its private base class 'Animal'
    Animal *p = &c;
                ^
Cat.cpp:24:13: note: declared private here
class Cat : private Animal {
            ^~~~~~~~~~~~~~
1 error generated.

出错原因:子类对象隐式转换为父类指针时出现错误,只要是 privateprotected 继承,子类的对象就无法转换为父类的地址。

【理解:不希望外界访问到父类中的所有属性和方法,为了达到这个目的,所以使用了私有继承。而子类地址转换为父类地址的操作可能使得外界能访问到父类的属性和方法,所以为了避免这种情况,就彻底不让进行地址转换。protected 继承同理。】

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-01-08 14:27:52  更:2022-01-08 14:28:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 6:45:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码