博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【C++】继承时的名字遮蔽&&派生类的构造函数
阅读量:4184 次
发布时间:2019-05-26

本文共 5575 字,大约阅读时间需要 18 分钟。

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

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

/*************************************************************************    > File Name: 继承_名字遮蔽.cpp    > Author: Tanswer_    > Mail: 98duxm@gmail.com    > Created Time: 2016年10月05日 星期三 17时50分36秒 ************************************************************************/#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
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;}//派生类--Studentclass 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: 19People--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 
#include
#include
#include
#include
#include
#include
#include
#include
#include
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();};/*派生类的构造函数写法1Student::Student(string name,int age,float score): People(name,age) { this -> score = score;}*///写法2Student::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 : 19score: 99

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

基类构造函数调用规则

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

/*************************************************************************    > File Name: 继承_派生构造.cpp    > Author: Tanswer_    > Mail: 98duxm@gmail.com    > Created Time: 2016年10月05日 星期三 22时32分18秒 ************************************************************************/#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
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: xxxage : 0score: 0name: 小明age : 19score: 99

  创建stu1时,执行Student::Student(),它并没有指明调用基类的哪个构造函数,系统默认调用不带参数的,如果将People::People()这个构造函数删除,则会发生编译错误,因为创建对象stu1时,没有调用基类的构造函数。

  创建stu2时,执行带参数的构造函数,它也指明了基类的构造函数。如果将Student::Student(string name ,int age,float score)函数中的People(name,age)去掉,就会调用基类的默认构造函数,输出结果变为 

name: xxxage : 0score: 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::PeopleStudent::Student()-----------------People::People(string, int )Student::Student(string ,int ,float )

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


转载地址:http://uluoi.baihongyu.com/

你可能感兴趣的文章
一道面试题深入了解java底层
查看>>
java下载附件
查看>>
cron表达式每个月最后一天
查看>>
Oracle中Like与Instr模糊查询性能大比拼
查看>>
Spring Boot入门===Hello World
查看>>
spring boot应用启动原理分析
查看>>
使用spring的好处
查看>>
微服务:分解应用以实现可部署性和可扩展性
查看>>
tcp_timestamps tcp_tw_recycle引起的服务器连接不上问题
查看>>
windows下ES和head插件的安装
查看>>
RAP一种更高效的前后端接口对接解决方案
查看>>
ELK(ElasticSearch, Logstash, Kibana)搭建实时日志分析平台
查看>>
ELK搭建教程(全过程)
查看>>
maven私服搭建使用
查看>>
Netty学习路线总结
查看>>
基于mybatis拦截器实现数据权限
查看>>
分布式文件系统FastDFS详解
查看>>
centos7上rabbitmq搭建
查看>>
rabbitmq集成spring的xml配置和java代码
查看>>
RabbitMQ消息确认(发送确认,接收确认)
查看>>