当前位置: 首页 > news >正文

成都网站建设g冠辰链接买卖平台

成都网站建设g冠辰,链接买卖平台,用自己的电脑做网站划算,政府 网站建设自查报告目录 一、派生类的默认成员函数 二、继承与友元 三、继承与静态成员 四、复杂的菱形继承及菱形虚拟继承 五、继承和组合 一、派生类的默认成员函数 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认构造函数,那么必须在派生…

目录

一、派生类的默认成员函数

二、继承与友元

三、继承与静态成员

四、复杂的菱形继承及菱形虚拟继承

五、继承和组合


 

 


一、派生类的默认成员函数

  1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认构造函数,那么必须在派生类的构造函数的初始化列表中显示调用基类的构造函数。

  2. 派生类的拷贝构造函数必须调用基类的拷贝构造函数完成基类的那一部分成员的拷贝初始化。

  3. 派生类的 operator= 必须调用基类的 operator= 完成基类的那一部分成员的赋值。

  4. 派生类的析构函数在被调用完后,会自动调用基类的析构函数清理基类的那一部分成员,即在派生类的析构函数中不用显示地调用基类的析构函数。

  5. 在创建派生类对象时,先调用基类的构造函数,再调用派生类的构造函数。

  6. 在销毁派生类对象时,先调用派生类的析构函数,再调用基类的析构函数。

#include <iostream>
using namespace std;
​
class Person
{
public:Person(const char* name = "张三", int age = 18): _name(name), _age(age){cout << "Person::default constructor" << endl;}
​Person(const Person& p): _name(p._name), _age(p._age){cout << "Person(const Person& p)" << endl;}
​Person& operator=(const Person& p){cout << "Person& operator=(const Person p)" << endl;if (this != &p){_name = p._name;_age = p._age;}return *this;}
​~Person(){cout << "~Person()" << endl;}
protected:string _name;  // 姓名int _age;  // 年龄
};
​
class Student : public Person
{
public:Student(const char* name = "张三", int age = 18, int stu_id = 0): Person(name, age), _stu_id(stu_id){cout << "Student::default constructor" << endl;}
​Student(const Student& s): Person(s), _stu_id(s._stu_id){cout << "Student(const Student& s)" << endl;}
​Student& operator=(const Student& s){cout << "Student& operator=(const Student& s)" << endl;if (this != &s){Person::operator=(s);  // operator=(s); 会陷入死循环_stu_id = s._stu_id;}return *this;}
​~Student(){cout << "~Student()" << endl;}
protected:int _stu_id;  // 学号
};
​
int main()
{Student s1("李四", 20, 1);// Person::default constructor// Student::default constructor
​Student s2(s1);// Person(const Person& p)// Student(const Student & s)
​Student s3;// Person::default constructor// Student::default constructor
​s3 = s1;// Student& operator=(const Student& s)// Person& operator=(const Person p)
​// ~Student()// ~Person()// ~Student()// ~Person()// ~Student()// ~Person()return 0;
}

 

 


二、继承与友元

友元关系不能继承,即基类友元不能访问子类私有和保护成员

#include <iostream>
using namespace std;
​
class Student;
class Person
{friend void Print(const Person& p, const Student& s);
protected:string _name = "张三";int _age = 18;
};
​
class Student : public Person
{// 必须声明,否则会报错friend void Print(const Person& p, const Student& s);  
protected:int _stu_id = 0;
};
​
void Print(const Person& p, const Student& s)
{cout << p._name << " " << p._age << endl;cout << s._stu_id << endl;
}
​
int main()
{Person p;Student s;Print(p, s);return 0;
}

 

 


三、继承与静态成员

如果基类定义了 static 静态成员,无论派生出了多少个类,在整个继承体系中都只有一个 static 静态成员实例

#include <iostream>
using namespace std;
​
class Person
{
public:Person() { ++_count; }
protected:string _name;int _age;
public:static int _count;  // static 静态成员变量
};
​
int Person::_count = 0;
​
class Student : public Person
{
protected:int _stu_id;
};
​
class Graduate : public Student
{
protected:string _seminarCourse;  // 研究科目
};
​
int main()
{cout << &Person::_count << " " << &Student::_count<< " " << &Graduate::_count << endl;// 输出的三个地址相同Person p1;Student s1;Student s2;Graduate g1;Graduate g2;Graduate g3;cout << Person::_count << endl;  // 6return 0;
}

 

 


四、复杂的菱形继承及菱形虚拟继承

单继承:一个派生类只有一个直接基类时,称这种继承关系为单继承。

多继承:一个派生类有两个或两个以上直接基类时,称这种继承关系为多继承。

菱形继承是多继承的一种特殊情况,它会造成数据冗余和二义性的问题,例如

#include <iostream>
using namespace std;
​
// 间接基类 A
class A
{
public:int _a;
};
​
// 直接基类 B
class B : public A
{
public:int _b;
};
​
// 直接基类 C
class C : public A
{
public:int _c;
};
​
// 派生类 D
class D : public B, public C
{
public:int _d;
};
​
int main()
{D d;// 为了消除歧义,必须在 _a 前面指明它具体来自哪个类d.B::_a = 0;d.C::_a = 1;d._b = 2;d._c = 3;d._d = 4;return 0;
}

f0745668420b4395a7ba770acb62a36c.png

 

为了解决菱形继承中的问题,C++ 提出了虚继承,使得在派生类中只保留一份间接基类的成员

在继承方式前面加上 virtual 关键字就是虚继承,例如

#include <iostream>
using namespace std;
​
// 间接基类 A
class A
{
public:int _a;
};
​
// 直接基类 B
class B : virtual public A  // 虚继承
{
public:int _b;
};
​
// 直接基类 C
class C : virtual public A  // 虚继承
{
public:int _c;
};
​
// 派生类 D
class D : public B, public C
{
public:int _d;
};
​
int main()
{D d;d._a = 1;  // okd._b = 2;d._c = 3;d._d = 4;return 0;
}

5d814df4b34a4815b1592c104b9111da.png

 

虚继承底层实现原理与编译器相关,一般是通过虚基类指针和虚基类表实现的

每个虚继承的子类都有一个虚基类指针,该指针指向一个虚基类表,表中记录了虚基类和本类的偏移量,通过这个偏移量就可以找到虚基类成员

当虚继承的子类被当作父类继承时,虚基类指针也会被继承

 

 


五、继承和组合

面向对象系统中功能复用的两种最常用技术是类继承对象组合(object composition)

类继承允许你根据基类的实现定义派生类的实现,这种通过生成派生类的复用通常被称为白箱复用(white-box reuse)。术语 "白箱" 是相对可视性而言的:在继承方式中,基类的内部细节对派生类可见。继承一定程度上破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类的依赖关系很强,耦合度高

对象组合是类继承之外的另一种复用选择,新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用(white-box reuse),因为对象的内部细节是不可见的,对象只能以 "黑箱" 的形式出现。组合类之间没有很强的依赖关系,耦合度低

因此在实际中,尽量多使用组合。不过继承也有用武之地的:public 继承是一种 is-a 的关系,即每个派生类对象都是一个基类对象,组合是一种 has-a 的关系,即假设 B 组合了 A,那么每个 B 类对象都有一个 A 类对象,而有些关系就适合用继承;另外要实现多态,也必须要用继承

例一

class Car
{
protected:string _color;  // 颜色string _num;  // 车牌号
};
​
class AITO : public Car
{
public:void Describe() const { cout << "Intelligent" << endl; }
};
​
class AVATR : public Car
{
public:void Describe() const { cout << "luxurious" << endl; }
};

AITO、AVATR 和 Car 构成 is-a 的关系

例二

class Tire
{
protected:string _brand;  // 品牌size_t _size;  // 尺寸
};
​
class Car
{
protected:string _color;string _num;Tire _t;
};

Car 和 Tire 构成 has-a 的关系

 

http://www.hkea.cn/news/30657/

相关文章:

  • 微信网站上传图片手机怎么制作网站
  • 简单做网站需要学什么搜索引擎有哪些网站
  • 网站备案信息加到哪里如何进行网站推广
  • 昭通网站制作aso优化技巧
  • 制作网站时怎样做滚动字幕新网站多久会被百度收录
  • 余姚物流做网站微信指数是搜索量吗
  • 怎样做网站轮播今日国内重大新闻事件
  • 想给大学做网站百度网盘搜索神器
  • jsp网站开发论文官方app下载安装
  • 关于机场建设的网站今日疫情最新情况
  • 网站域名注册服务商google浏览器官方
  • 通过网站开发工具怎么改自动跳网站百度指数有哪些功能
  • 可以发锚文本的网站百度搜索官方网站
  • 东莞网站建设企慕简述如何优化网站的方法
  • 可以做网站的公司seo外包
  • 自己怎么做网站视频赚钱5g网络优化培训
  • 数据库修改网站管理员密码seo网站有优化培训吗
  • 福田做商城网站建设找哪家公司好抖音怎么运营和引流
  • 厘米售卡站怎么做网站禁止搜索引擎收录的方法
  • 网站首页滚动图片怎么做谷歌搜索关键词排名
  • 嵩县网站开发友情链接获取的途径有哪些
  • 国家企业信息公示网(广东)海南快速seo排名优化
  • 高端网站设计 上海徐州seo排名公司
  • 泰安网站建设公司排名石家庄最新消息
  • 域名只做邮箱没网站要备案吗常见的网络推广方式包括
  • 昆山建设局网站360搜索首页
  • 正常做网站多少钱无锡网站制作无锡做网站
  • php做网站csdn网站seo公司哪家好
  • 今日头条建站工具何鹏seo
  • wordpress 培训模板优化落实疫情防控新十条