您的位置:首页 > 编程语言 > C语言/C++

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

2016-10-08 15:28 232 查看

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

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

/*************************************************************************
> 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 )


从上面可以看出,构造函数的调用顺序是按照继承的层次自顶向下、从基类再到派生类的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐