如果派生类和基类中的成员相同,会发生什么情况呢?
如果派生类和基类的成员变量或者成员函数相同,那么就会遮蔽从基类继承来的成员函数或者成员变量,即使用新增的成员变量,而不是使用继承来的。
/*************************************************************************
> 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 )
从上面可以看出,构造函数的调用顺序是按照继承的层次自顶向下、从基类再到派生类的。