【C++】继承时的名字遮蔽&&派生类的构造函数
2016-10-08 15:28
302 查看
如果派生类和基类中的成员相同,会发生什么情况呢?
如果派生类和基类的成员变量或者成员函数相同,那么就会遮蔽从基类继承来的成员函数或者成员变量,即使用新增的成员变量,而不是使用继承来的。/************************************************************************* > 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++继承与派生之二】有子对象的派生类的构造函数
- C++学习之路—继承与派生(二):派生类的构造函数与析构函数
- C++继承具体解释之二——派生类成员函数具体解释(函数隐藏、构造函数与兼容覆盖规则)
- 【c++继承】继承关系中派生类对象构造函数和析构函数调用顺序
- 【C++继承与派生之二】有子对象的派生类的构造函数
- 从零开始学C++之继承(二):继承与构造函数、派生类到基类的转换
- c++学习笔记5,多重继承中派生类的构造函数与析构函数的调用顺序(二)
- C++构造函数 & 拷贝构造函数 & 派生类的构造函数 & 虚继承的构造函数
- [C++]派生类构造函数举例(多继承、含有内嵌对象)
- C++中类的继承与Java中的不同,C++的派生类不能继承父类的构造函数和析构函数(不一定正确)
- c++ Prime(第六版) P486 类继承 派生类构造函数
- 从零开始学C++之继承(二):继承与构造函数、派生类到基类的转换
- C++继承详解之二——派生类成员函数详解(函数隐藏、构造函数与兼容覆盖规则)
- C++ 基类构造函数带参数的继承方式及派生类的初始化
- C++ 虚继承派生类构造函数的写法
- C++基础(九)继承与派生——派生类成员的构造函数和析构函数
- C++中虚继承派生类构造函数的正确写法
- 从零开始学C++之继承(二):继承与构造函数、派生类到基类的转换
- c++ 单继承派生类的构造函数
- C++构造函数 & 拷贝构造函数 & 派生类的构造函数 & 虚继承的构造函数