【C++】继承时的名字遮蔽&&派生类的构造函数

c++学习总结 本文深入探讨了C++继承体系中的关键概念,包括: 名字遮蔽机制:当派生类定义与基类同名的成员时,基类成员会被遮蔽,可通过显式域解析符访问; 类作用域规则:每个类构成独立作用域,继承形成嵌套作用域,成员查找遵循派生类优先原则; 多态实现:通过虚函数和基类指针/引用实现动态绑定,详细解析了虚函数表(vtable)和虚表指针(vptr)的工作原理; 继承关系特性:包括公有继承权限、对象切片、基类指针/引用指向派生类对象等特殊行为; 多继承问题:重点分析了菱形继承的数据冗余和二义性问题,以及虚继承的解决方案; 多 阅读详情

如果派生类和基类中的成员相同,会发生什么情况呢?

  如果派生类和基类的成员变量或者成员函数相同,那么就会遮蔽从基类继承来的成员函数或者成员变量,即使用新增的成员变量,而不是使用继承来的。

/*************************************************************************
    > File Name: 继承_名字遮蔽.cpp
    > Author: Tanswer_
    > Mail: 98duxm@gmail.com
    > Created Time: 2016年10月05日 星期三 17时50分36秒
 ************************************************************************/

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;

//基类
class People
{
protected:
    string  name;
    int     age;
public:
    void    setName(string );
    void    setAge(int );
    string  getName();
    int     getAge();
    void display();
};

/*基类中的display()函数*/
void People::display()
{
    cout << "People--name: " << name << "    age:" << age << endl;
}

void People::setName(string name)
{
    this->name = name;
}


void People::setAge(int age)
{
    this->age = age;
}

string People::getName()
{
    return name;
}

int People::getAge()
{
    return this->age;
}

//派生类--Student
class Student: public People
{
private:
    float   score;
public:
    using People::name;
    using People::age;
    void    setScore(float );
    float   getScore();
    void    display();
};

/*派生类中的display()函数*/
void Student::display()
{
    cout << "Stu name: " << name << "  age: " << age << endl;    
}

void Student::setScore(float score)
{
    this->score = score;
}

float Student::getScore()
{
    return score;
}

int main()
{
    Student stu;
    stu.setName("小明");
    stu.setAge(19);
    stu.setScore(99.9f);

   // cout << stu.getName() << "   年龄是: " << stu.getAge() << "   成绩是:" << stu.getScore() << endl;
    stu.display();
    stu.People::display();

    return 0;
}

输出结果为:

Stu name: 小明  age: 19
People--name: 小明    age:19

  本例中基类和派生类都定义了display()成员函数,会造成遮蔽,stu 是Student的对象,所以默认使用派生类Student中的display()。不过基类People中的display()函数仍然可以访问,只是要加上类名和域解析符。

派生类的构造函数

基类的构造函数不能被继承,所以声明派生类的时候,对基类的成员的初始化也要由派生类的构造函数来完成。

解决这个问题的思路是:执行派生类的构造函数时,要把基类的构造函数加上。

/*************************************************************************
    > File Name: 继承_派生构造.cpp
    > Author: Tanswer_
    > Mail: 98duxm@gmail.com
    > Created Time: 2016年10月07日 星期五 22时32分18秒
 ************************************************************************/

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;
class People
{
protected:
    string name;
    int age;
public:
    People(string ,int );  //基类构造函数声明
};

//基类构造函数
People::People(string name,int age): name(name),age(age) {}

//派生类
class Student: public People
{
private:
    float score;
public:
    Student(string ,int ,float );
    void display();
};

/*派生类的构造函数写法1
Student::Student(string name,int age,float score): People(name,age) {
    this -> score = score;
}
*/

//写法2
Student::Student(string name,int age,float score) :People(name,age),score(score) {}

void Student::display()
{
    cout << "name: " << name << endl;
    cout << "age : " << age << endl;
    cout << "score: " << score << endl;
}

int main()
{
    Student stu("小明",19,99.0);
    stu.display();

    return 0;
}

输出结果:

name: 小明
age : 19
score: 99

  我们可以看到上面两种写法,要注意的是 派生类冒号后面是对基类构造函数的调用而不是声明,括号里的参数是实参,不仅可以写变量,还可以写常量、局部变量等。

基类构造函数调用规则

  事实上,通过派生类创建对象时必须要调用基类的构造函数,这是语法规定。定义派生类构造函数时最好指明基类构造函数,如果基类有默认构造函数(不带参数的构造函数),那么可以不指明,系统会默认调用,如果没有,那么必须要指明,否则系统不知道如何调用基类的构造函数,编译失败。

/*************************************************************************
    > File Name: 继承_派生构造.cpp
    > Author: Tanswer_
    > Mail: 98duxm@gmail.com
    > Created Time: 2016年10月05日 星期三 22时32分18秒
 ************************************************************************/

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;
class People
{
protected:
    string name;
    int age;
public:
    People();
    People(string ,int );
};

/*基类构造函数带参数的构造函数*/
People::People(string name,int age): name(name),age(age) {}

/*不带参数*/
People::People() {
    this -> name = "xxx";
    this -> age = 0;
}

//派生类
class Student: public People
{
private:
    float score;
public:
    Student();
    Student(string ,int ,float );
    void display();
};

/*带参数的构造函数*/
Student::Student(string name,int age,float score) :People(name,age),score(score) {}

/*不带参数*/
Student::Student(){
    this -> score = 0.0;
}

void Student::display()
{
    cout << "name: " << name << endl;
    cout << "age : " << age << endl;
    cout << "score: " << score << endl;
}

int main()
{
    Student stu1;
    stu1.display();

    Student stu2("小明",19,99.0);
    stu2.display();

    return 0;
}

输出结果为:

name: xxx
age : 0
score: 0
name: 小明
age : 19
score: 99

  创建stu1时,执行Student::Student(),它并没有指明调用基类的哪个构造函数,系统默认调用不带参数的,如果将People::People()这个构造函数删除,则会发生编译错误,因为创建对象stu1时,没有调用基类的构造函数。
  创建stu2时,执行带参数的构造函数,它也指明了基类的构造函数。如果将Student::Student(string name ,int age,float score)函数中的People(name,age)去掉,就会调用基类的默认构造函数,输出结果变为 

name: xxx
age : 0
score: 99

 构造函数的调用顺序

为了直观地看清这个问题,我们把上面的程序修改一下。

/*基类构造函数*/
People::People(string name,int age): name(name),age(age) {
    cout << "People::People(string, int )" << endl;
}

People::People() {
    this -> name = "xxx";
    this -> age = 0;
    cout << "People::People" << endl;
}
/*派生类*/
Student::Student(string name,int age,float score) :People(name,age),score(score) {
    cout << "Student::Student(string ,int ,float )" << endl;
}

Student::Student(){
    this -> score = 0.0;
    cout << "Student::Student()" << endl;
}

主函数 我们这样写:

{
    Student stu1;
    //stu1.display();

    cout << "-----------------" << endl;
    Student stu2("小明",19,99.0);
    //stu2.display();

    return 0;
}

输出结果为:

People::People
Student::Student()
-----------------
People::People(string, int )
Student::Student(string ,int ,float )

从上面可以看出,构造函数的调用顺序是按照继承的层次自顶向下、从基类再到派生类的。


c++继承构造函数 【1】为什么需要继承构造函数? 首先,看看如下代码片段: 1 struct A 2 { 3 A(int i) 4 {} 5 }; 6 7 struct B : A 8 { 9 B(int i) : A(i) 10 {} 11 }; 在C++中非常常见:B派生于A,B在构造函数中调用A的构造函数,从而完成构造函数的“传递”。 有时候,基类可能拥有数量众多的不同版本的构造函数(这样的情况并不少见)。 那么,倘若基类中有大量的构造函数 阅读详情

相关推荐

[C++ 从入门到精通] 13.派生类、调用顺序、继承方式、函数遮蔽

派生类:在C++中,继承就是在一个已存在的类的基础上建立一个新的类。已存在的类称为「基类」,又称为「父类」;新建立的类称为「派生类」,又称为「子类」

Loewen丶的小窝 1338

C++继承时的名字遮蔽问题

C++继承时的名字遮蔽问题

Elanie1024的博客 501

高程 | 继承与派生(c++)

类的继承,是新的类从已有类那里得到已有的特性。类的派生,从已有类产生新类的过程。

知识库搭建ing 2943

c++基本使用--名字遮蔽与类作用域/继承的特殊关系

名字遮蔽与类作用域/继承的特殊关系

记录我目之所及的世界 267

从SFF-8087到SFF-8643:详解服务器硬盘背板连接线缆的演变与实战接线

本文深度解析了服务器硬盘背板连接技术从SFF-8087到SFF-8643的演进历程,重点介绍了SAS、SATA和U.2接口的技术特点与实战接线方案。通过对比不同连接器标准的物理特性和电气规范,提供了混合环境下的线缆选择策略和常见故障排查指南,帮助IT专业人员优化存储系统性能与稳定性。

weixin_30603633的博客 275

《数据分析岗笔试高频题:字节常用的SQL与AB测试考题解析》

• 核心考点:用RANK()/DENSE_RANK()/ROW_NUMBER()排序,SUM() OVER()计算累积值。◦ 用公式n=2*(Zα/2+Zβ)^2*σ²/δ²,取α=0.05,β=0.2,计算得每组需260人;◦ 关注字节技术公众号“字节跳动数据团队”,学习真实AB测试案例(如“推荐算法优化实验”)。• 题型分布:SQL编程题(40%)、AB测试方案设计(30%)、数据洞察题(30%);◦ 牛客网“字节跳动SQL真题”(如“统计用户7日留存”“广告投放ROI计算”)。

2501_91651594的博客 1107

20180321 C++ 避免遮掩继承而来的名称

20180321 C++ 避免遮掩继承而来的名称C++的名称遮掩规则(name-hiding relue)所做的唯一事情就是:遮掩名称。至于名称是否是相同或不同的类型,并不重要,如double类型的局部变量x遮掩了int类型的全局变量x。现在考虑继承关系:eg:class Base{private:  int x;public :  virtual void mf1() = 0;  virtual...

weixin_39089680的博客 295

飞塔防火墙CVE-2022-40684漏洞复现:手把手教你搭建靶场环境(附调试技巧)

本文详细指导如何搭建Fortinet飞塔防火墙CVE-2022-40684认证绕过漏洞的靶场环境,涵盖虚拟机部署、网络配置、调试模式开启及漏洞原理分析。通过手把手教程,读者可掌握漏洞复现与深度调试技巧,深入理解该认证绕过漏洞的利用与防御。

h6i7j8的博客 695

C++ 继承详解

C++ 继承继承语法继承方式改变访问权限名字遮蔽继承时的对象模型无变量遮蔽有变量遮蔽 继承语法 继承的一般语法为: class 派生类名:[继承方式] 基类名{ 派生类新增加的成员 }; 继承方式 继承方式包括 public(公有的)、private(私有的)和 protected(受保护的),此项是可选的,如果不写,那么默认为 private。不同的继承方式会影响基类成员在派生类中的访问权限。 (1)public继承方式 基类中所有 public 成员在派生类中为 public 属性; 基类中

TABE_的博客 1万+

当兵心理测试软件,当兵心理测试题及答案

心理测试是一种比较先进的测试方法,它是指通过一系列手段,将人的某些心理特征数量化,来衡量个体心理因素水平和个体心理差异差异的一种科学测量方法。小编为你整理了当兵心理测试题及答案,希望对你有所参考帮助。征兵心理测试题(1代表是2代表否)1、我的胃口很好。12、我早上起来的时候,多半觉得睡眠充足,头脑清醒13、我喜欢看报纸上的犯罪新闻。14、有时我常感到困难重重,无法克服。25、我时常遇见一些所谓的专...

weixin_42128393的博客 1万+

AUTOSAR模式管理-EcuM多核处理及其他概念

因此,EcuM不请求状态。因此,BswM必须确保,例如,在调用EcuM_GoHalt或EcuM_GoPoll之前,必须将关机目标从其默认值更改为ECUM_STATE_SLEEP。对于ECU的关闭,BswM(位于主EcuM的同一个分区中)最终调用主核上的GoOff,该GoOff将请求分发给所有的从核。在ECU Manager模块的早期版本中,睡眠目标被特殊处理,因为在ECU中实现的睡眠模式取决于ECU的功能。在使用了外部的SBC控制相关的MCU的下电的时候,在OFF阶段最后调用SBC进入到Sleep的指令。

m0_49148264的博客 1340

C++基础——继承时的名字遮蔽问题

如果派生类中的成员(包括成员变量和成员函数)和基类中的成员重名,那么就会遮蔽从基类继承过来的成员。所谓遮蔽,就是在派生类中使用该成员(包括在定义派生类时使用,也包括通过派生类对象访问该成员)时,实际上使用的是派生类新增的成员,而不是从基类继承来的。 下面是一个成员函数的名字遮蔽的例子: #include<iostream> using namespace std; //基类People class People{ public: void show(); protec...

一个小孩 365

【SpringBoot笔记44】SpringBoot多数据源配置(方式一:配置多个mapper扫描不同的包路径实现多数据源配置)

在SpringBoot应用开发中,一般情况下,都是只会配置一个数据源信息,之后整个工程都是对当前数据源进行增删改查的操作。但是,在实际开发里面,也有可能会遇到多数据源的情况,例如:当前工程中除了需要访问自己应用的数据库,还需要直接连接第三方系统的数据库进行业务处理,这种情况下,就需要进行多数据源的配置。SpringBoot考虑到了这一点,所以它是支持多数据源的配置的,下面介绍一下如何配置多数据源。

✅ Java 开发工程师 1116

C++继承时名字的遮蔽

如果派生类中的成员(包括成员变量和成员函数)和基类中的成员重名,那么就会遮蔽从基类继承过来的成员。所谓遮蔽,就是在派生类中使用该成员(包括在定义派生类时使用,也包括通过派生类对象访问该成员)时,实际上使用的是派生类新增的成员,而不是从基类继承来的。 成员函数的名字遮蔽: #include<iostream> using namespace std; //基类People class ...

weixin_45743799的博客 332

全球APN信息汇总

全球APN信息,电信APN,移动APN,联通APN,台湾APN,马来西亚APN,俄罗斯APN,日本APN,泰国APN,美国APN,英国APN,法国APN,德国APN,意大利APN,葡萄牙APN,土耳其APN,荷兰APN,丹麦APN,比利时APN,爱尔兰APN,新加坡APN,越南APN,老挝APN,菲律宾APN,印尼APN,泰国APN,柬埔寨APN,巴基斯坦APN,印度APN,奥地利APN,保加利亚APN,捷克APN,立陶宛APN,罗马尼亚APN,挪威APN,希腊APN,匈牙利APN,瑞士APN,乌克兰APN

renkai721的专栏 2796

Pdu Router(PduR)模块

1. PduR路由基本功能 2. PduR总线网关功能 3. PduR缓存机制 4. 总结

weixin_43759043的博客 3849

c++继承和派生(个人总结笔记)

一、继承和派生 1、C++继承的概念及语法 继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承类似,例如儿子继承父亲的财产。 继承(Inheritance) 可以理解为一个类从另一个类获取成员变量和成员函数的过程。例如类 B 继承于类 A,那么 B 就拥有 A 的成员变量和成员函数。被继承的类称为父类或基类,继承的类称为子类或派生类。 继承方式包括 public(公有的)、private(私有的)和 protected(受保护的),此项是可选的,如果不写,那么默认为 priva

junxuezheng的博客 2292

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++继承详解

小编这些年深知大多数初中级Java工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。因此我收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。原文链接:https://gitee.com/hh090807。

song99911的博客 1100

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

C++基础 名字遮蔽

问答: 什么叫名字遮蔽? 派生类中的成员(包括成员变量和成员函数)和基类中的成员重名,那么就会遮蔽从基类继承过来的成员,这就叫做名字遮蔽。 有一点要提出,对于继承而言,只要名字一样不管形参个数和类型怎样,都构成名字遮蔽。 会产生怎样的后果? 派生类并没有继承到基类的重名的成员函数,它用的是自己的成员函数。换句话说,派生类自己的重名函数把基类的给覆盖了,导致派生类自己使用自己的不能使用基类的。

识海拾贝的博客 598

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

C++——名字遮蔽与类的作用域

C++——类的作用域以及继承的特殊关系

MaoSiri的博客 694

C++继承时的名字遮蔽

如果派生类中的成员(包括成员变量和成员函数)和基类中的成员重名,那么就会遮蔽从基类继承过来的成员。所谓遮蔽,就是在派生类中使用该成员(包括在定义派生类时使用,也包括通过派生类对象访问该成员)时,实际上使用的是派生类新增的成员,而不是从基类继承来的。 范例 #include<iostream> using namespace std; //基类People class People{ public: void show(); protected: char *m_nam

zzwwgg1984的博客 180

C++学习16 继承时的名字遮蔽

如果派生类中的成员变量和基类中的成员变量重名,那么就会遮蔽从基类继承过来的成员变量。所谓遮蔽,就是使用新增的成员变量,而不使用继承来的。 成员函数也一样,如果函数名和参数签名都相同,就会造成遮蔽。如果仅仅是函数名相同,而参数签名不同,那么会构成重载。 请看下面的例子: #include<iostream> using namespace std; class P...

dengaoxin0873的博客 147

C++继承和派生

被继承的类称为父类或基类,继承的类称为子类或派生类。“子类”和“父类”通常放在一起称呼,“基类”和“派生类”通常放在一起称呼。派生类除了拥有基类的成员,还可以定义自己的新成员,以增强类的功能。以下是两种典型的使用继承的场景:1) 当你创建的新类与现有的类相似,只是多出若干成员变量或成员函数时,可以使用继承,这样不但会减少代码量,而且新类会拥有基类的所有功能。2) 当你需要创建多个类,它们拥有很多相似的成员变量或成员函数时,也可以使用继承。

tecoes的博客 1108
上一篇: 【C++】继承语法&&继承方式
下一篇: 【C++】智能指针的设计与实现
Tanswer_
博客等级 码龄11年 231粉丝 91原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值