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

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

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

/*************************************************************************
    > File Name: 继承_名字遮蔽.cpp
    > Author: Tanswer_
    > Mail: [email protected]
    > 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;
}

//派生类--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: [email protected]
    > 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();
};

/*派生类的构造函数写法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: [email protected]
    > 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: 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++,继承,派生时构造函数)