免费黄页网站,公司网站登陆后台管理中心不能修改前台主页,家居seo整站优化方案,做兼职最好的网站有哪些目录
一、继承的概念
二、基类和派生类对象赋值转换
三、继承的作用域
四、派生类的默认成员函数
五、继承与友元
六、继承与静态成员变量
七、菱形继承与虚拟继承 一、继承的概念
继承是指一个类可以通过继承获得另一个类的属性和方法#xff0c;扩展自己的功能…目录
一、继承的概念
二、基类和派生类对象赋值转换
三、继承的作用域
四、派生类的默认成员函数
五、继承与友元
六、继承与静态成员变量
七、菱形继承与虚拟继承 一、继承的概念
继承是指一个类可以通过继承获得另一个类的属性和方法扩展自己的功能提高了代码的复用性增加了类与类之间的耦合性。
继承机制允许程序员在保持原有类特性的基础上进行扩展增加功能产生新的派生类。
#define _CRT_SECURE_NO_WARNINGS 1#include iostream
using namespace std;class Person
{
public:void Print(){cout name: _name , age: _age endl;}private:string _name unknow;int _age 0;
};class Student : public Person
{
private:string _stuID ;
};class Teacher : public Person
{
private:string _jobID ;
};int main()
{Student s;Teacher t;cout typeid(s).name() endl;cout typeid(t).name() endl;s.Print();t.Print();return 0;
}
类成员 / 继承方式public继承protect继承private继承基类的public成员派生类的public成员派生类的protect成员派生类的private成员基类的protect成员派生类的protect成员派生类的protect成员派生类的private成员基类的private成员派生类中不可见派生类中不可见派生类中不可见
由上表可见类的继承遵循权限缩小原则与函数传参类似。 二、基类和派生类对象赋值转换 #define _CRT_SECURE_NO_WARNINGS 1#include iostream
using namespace std;class Person
{
protected:string _name; // 姓名string _sex; // 性别int _age; // 年龄
};class Student : public Person
{
public:int _No; // 学号
};void Test()
{Student sobj;// 1.子类对象可以赋值给父类对象/指针/引用Person pobj sobj;Person* pp sobj;Person rp sobj;//2.基类对象不能赋值给派生类对象sobj pobj;// 3.基类的指针可以通过强制类型转换赋值给派生类的指针pp sobj;Student* ps1 (Student*)pp; // 这种情况转换时可以的。ps1-_No 10;pp pobj;Student* ps2 (Student*)pp; // 这种情况转换时虽然可以但是会存在越界访问的问题ps2-_No 10;
} 三、继承的作用域
在继承体系中基类和派生类都有独立的作用域子类和父类中有同名成员子类成员将屏蔽父类对同名成员的直接访问这种情况叫隐藏也叫重定义。在子类成员函数中可以使用 基类::基类成员 显示访问。
#define _CRT_SECURE_NO_WARNINGS 1#include iostream
using namespace std;// Student的_num和Person的_num构成隐藏关系可以看出这样代码虽然能跑但是非常容易混淆
class Person
{
protected:string _name 小李子; // 姓名int _num 111; // 身份证号
};class Student : public Person
{
public:void Print(){cout 姓名: _name endl;cout 身份证号: Person::_num endl;cout 学号: _num endl;}protected:int _num 999; // 学号
};int main()
{Student s1;s1.Print();
}; 四、派生类的默认成员函数
派生类对象初始化先调用基类构造再调派生类构造。
派生类对象析构清理先调用派生类析构再调基类的析构
派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
派生类的operator必须要调用基类的operator完成基类的复制。
#define _CRT_SECURE_NO_WARNINGS 1#include iostream
using namespace std;class Person
{
public:Person(const char* name peter): _name(name){cout Person() endl;}Person(const Person p): _name(p._name){cout Person(const Person p) endl;}Person operator(const Person p){cout Person operator(const Person p) endl;if (this ! p)_name p._name;return *this;}~Person(){cout ~Person() endl;}protected:string _name; // 姓名
};class Student : public Person
{
public:Student(const char* name, int num): Person(name), _num(num){cout Student() endl;}Student(const Student s): Person(s), _num(s._num){cout Student(const Student s) endl;}Student operator (const Student s){cout Student operator (const Student s) endl;if (this ! s){Person::operator (s);_num s._num;}return *this;}~Student(){cout ~Student() endl;}protected:int _num; //学号
};int main()
{Student s1(jack, 18);Student s2(s1);Student s3(rose, 17);s1 s3;
}/*
Person()
Student()
Person(const Person p)
Student(const Student s)
Person()
Student()
Student operator (const Student s)
Person operator(const Person p)
~Student()
~Person()
~Student()
~Person()
~Student()
~Person()
*/ 五、继承与友元
友元函数定义在类外部可以访问类的私有成员和保护成员。
友元关系不能继承也就是说基类友元不能访问子类私有和保护成员。
#define _CRT_SECURE_NO_WARNINGS 1#include iostream
using namespace std;#define _CRT_SECURE_NO_WARNINGS 1class Student;class Person
{
public:friend void Display(const Person p, const Student s);
protected:string _name; // 姓名
};class Student : public Person
{
protected:int _stuNum; // 学号
};void Display(const Person p, const Student s)
{cout p._name endl;cout s._stuNum endl; // 无法访问
}void main()
{Person p;Student s;Display(p, s);
} 六、继承与静态成员变量
基类定义了static静态成员则整个继承体系里面只有一个这样的成员。无论派生出多少个子类都只有一个static成员实例 。
#define _CRT_SECURE_NO_WARNINGS 1#include iostream
using namespace std;#define _CRT_SECURE_NO_WARNINGS 1class Person
{
public:Person() { _count; }
protected:string _name; // 姓名
public:static int _count; // 统计人的个数。
};// 静态成员在类外部赋值
int Person::_count 0;class Student : public Person
{
protected:int _stuNum; // 学号
};class Graduate : public Student
{
protected:string _seminarCourse; // 研究科目
};void main()
{Student s1;Student s2;Student s3;Graduate s4;cout 人数 : Person::_count endl;Student::_count 0;cout 人数 : Person::_count endl;
} 七、菱形继承与虚拟继承
菱形继承是多继承的一种特殊情况但是菱形继承有数据冗余和二义性的问题。 #define _CRT_SECURE_NO_WARNINGS 1#include iostream
using namespace std;#define _CRT_SECURE_NO_WARNINGS 1
class Person
{
public:string _name; // 姓名
};class Student : public Person
{
protected:int _num; //学号
};class Teacher : public Person{
protected:int _id; // 职工编号
};class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};void main()
{// 这样会有二义性无法明确知道访问的是哪一个Assistant a;a._name peter; // 报错Assisitant::_name 不明确// 需要显示指定访问哪个父类的成员可以解决二义性问题但是数据冗余问题无法解决a.Student::_name xxx;a.Teacher::_name yyy;
}
虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系在Student和Teacher的继承Person时使用虚拟继承即可解决问题。需要注意的是虚拟继承不要在其他地方去使用。
#define _CRT_SECURE_NO_WARNINGS 1#include iostream
using namespace std;#define _CRT_SECURE_NO_WARNINGS 1
class Person
{
public:string _name; // 姓名
};class Student : virtual public Person
{
protected:int _num; //学号
};class Teacher : virtual public Person{
protected:int _id; // 职工编号
};class Assistant : public Student, public Teacher
{
protected:string _majorCourse; // 主修课程
};void main()
{// 这样会有二义性无法明确知道访问的是哪一个Assistant a;a._name peter; // 报错Assisitant::_name 不明确// 需要显示指定访问哪个父类的成员可以解决二义性问题但是数据冗余问题无法解决a.Student::_name xxx;a.Teacher::_name yyy;
} 虚继承会维护一张虚基表每个虚成员函数的类都指向虚基表的指针通过虚基表中存储的偏移量找到公共父类的成员变量。