本文共 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/