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

网站建设中小姐关键词代发排名

网站建设中,小姐关键词代发排名,抚宁网站建设,网站域名设置本节课要点: 继承特性多态虚函数目录 一、多继承 二、继承的前提:正确的分类 三、多态 1. 虚函数 2. 确保覆盖和终止覆盖 3. 虚函数的实现原理 4. 虚析构函数 四、纯虚函数和抽象类 1. 纯虚函数 2. 抽象类 一、多继承 在之前的课程中&a…

本节课要点:

  • 继承
  • 特性
  • 多态
  • 虚函数

目录

一、多继承 

二、继承的前提:正确的分类 

三、多态

1. 虚函数

2. 确保覆盖和终止覆盖

3. 虚函数的实现原理

4. 虚析构函数 

四、纯虚函数和抽象类

1. 纯虚函数 

2. 抽象类 


一、多继承 

在之前的课程中,我们已经构建了自己的双向链表类。双向链表是一种线性表,线性表的作用是存储数据,故又称容器。学习了第六章:继承之后,我们会发现两者之间存在着Is-a关系,即双向链表是一种容器。因此,双向链表类应继承自容器类,即容器类是双向链表类的父类。 

下面考察 container 类(容器类) :

// container.h#pragma once#include "value_type.h"struct container {using value_type = ::value_type;using pointer = value_type*;using reference = value_type&;
};// traits
struct is_traversible {enum : bool {value = true}; // 枚举常量取的是bool值bool operator()() { // 这个重载使得结构体成为了可调用对象return value;}// 为了使用reference,把这段copy过来using value_type = ::value_type;using pointer = value_type*;using reference = value_type&;using callback = void (reference);
};

is_traversible 可遍历的,是所有容器共有的一种特性。

双向链表类继承容器类和特性类:

// dlist.h...class dlist : public container, public is_traversible { // 多继承
public:// typename container::value_type表明类型来自父类,typename指明这是一种类型using value_type = typename container::value_type;using pointer = typename container::pointer;using reference = typename container::reference;private:// 定义回调函数类型// using callback = void (reference);using is_traversible::callback;...};

特性介于继承和混入(mix-in)之间,但在C++中采用继承的方式来实现。

 

二、继承的前提:正确的分类 

考虑雇员、经理、销售员三者之间的关系,以下是一种错误的分类:

// employee.h#pragma once#include <iostream>
#include <string>class employee {
protected:job * j; // 赋值兼容原则public:const std::string name;// 只能在初始化列表初始化常量,否则就变成了赋值employee(job * j, const std::string& n) : j(j), name(n) {}~employee() {}void aboutme() {std::cout << name << ':' << j->title << std::endl;}
};class manager : public employee {using employee::employee; // 继承构造函数
};class salesperson : public employee {using employee::employee;
};

 修正后:

//employee.h#pragma once#include <iostream>
#include <string>struct job {std::string title;int salary;job(const std::string & t, int s) : title(t), salary(s) {}
};struct manager : public job {manager(int s = 10000) : job("manager", s) {}
};struct salesperson : public job {salesperson(int s = 5000) : job("salesperson", s) {}
};class employee {
protected:job * j;public:const std::string name;employee(job * j, const std::string& n) : j(j), name(n) {}~employee() {}void aboutme() {std::cout << name << ':' << j->title << std::endl;}
};

雇主和雇员是按照身份来分的,销售员和经理是按照职位来分的。

销售员和经理是一种角色(role),是可以互相转换的。而我们之前谈到的双向链表和数组是不会互相转换的,它们的关系铁铁的。

 

三、多态

回到之前的多边形类,我们试图求取各多边形的面积:

// poly.cpp#include <iostream>class poly {
protected://共性std::string ids;size_t edge;public:poly(std::string _ids = "poly", size_t e = 0) : ids(_ids), edge(e) {}~poly() {}std::string what() const {return ids;}double area() const {return 0.0;}
};class quad : public poly {
public:quad(std::string _ids = "quad") : poly(_ids, 4) {}~quad() {}
};class para : public quad {
protected:double width, height;public:para(double w = 1, double h = 1, std::string _ids = "para") : quad(_ids), width(w), height(h) {}~para() {}double area() const override {return width * height;}
};class rect : public para {
public:rect(double w = 1, double h = 1, std::string _ids = "rect") : para(w, h, _ids) {}~rect() {}
};class square final : public rect {
public:square(double w = 1) : rect(w, w, "square") {}~square() {}
};int main() {quad *quads[] = { new para(7, 4), new rect(10, 5), new square(8) };for (auto q : quads) {std::cout << q->what() << ' ' << q->area() << std::endl;delete q;}return 0;
}

输出结果:

para 0
rect 0
square 0

据分析,这里的三个形体使用的都是其父类 quad 的 area() 方法。原因是:我们使用的是父类 quad 的指针指向的子类对象,导致内存被重解释了。quad 认为自己指向的就是一个 quad 对象,因此便调用了父类子对象的 area() 方法。

因此,我们需要使用子类的方法覆盖父类的同原型方法。 

1. 虚函数

若要使子类的成员函数能够覆盖父类的同原型成员,则必须将父类的该成员说明是虚函数。关键字 virtual 明确地告诉编译器:这是一个虚函数;该类子类中的同名版本将覆盖这个版本。 

class poly {
protected:std::string ids;size_t edge;public:poly(std::string _ids = "poly", size_t e = 0) : ids(_ids), edge(e) {}~poly() {}std::string what() const {return ids;}virtual double area() const {return 0.0;}
};

虚特性能够被继承。如果子类原型一致地重载了父类的某个虚函数,那么即使在子类中没有将这个函数显式说明成是虚的,它也会被编译器认为是虚函数。 

 

2. 确保覆盖和终止覆盖

被 override 描述符修饰的函数明确地告诉编译器,自己是一个覆盖版本。 

class para : public quad {
protected:double width, height;public:para(double w = 1, double h = 1, std::string _ids = "para") : quad(_ids), width(w), height(h) {}~para() {}double area() const override {return width * height;}
};

final 描述符能有效终止虚函数的覆盖,或者后继继承的发生。 

class square final : public rect {
public:square(double w = 1) : rect(w, w, "square") {}~square() {}
};

 

3. 虚函数的实现原理

考察下述代码:

// sizeof-class-with-virtual.cpp#include <iostream>// alignof(类型) 向该类型对齐
class alignas(8) noVirtual { // align对齐 alignas(8)八字节对齐char a;void f() {}
};// 按道理来说,函数是不占类对象大小的
class alignas(8) oneVirtual {char a;virtual void f() {}
};class alignas(8) manyVirtual {char a;virtual void f() {}virtual int g() {return 0;}virtual double h(double) {return 1.0;}
};int main() {std::cout << "size of noVirtual: " << sizeof(noVirtual) << std::endl;std::cout << "size of oneVirtual: " << sizeof(oneVirtual) << std::endl;std::cout << "size of manyVirtual: " << sizeof(manyVirtual) << std::endl;std::cout << "ref: size of pointer: " << sizeof(void *) << std::endl;return 0;
}

输出结果:

size of noVirtual: 8
size of oneVirtual: 16 # 这多出的8个字节是编译器干的
size of manyVirtual: 16
ref: size of pointer: 8 # 给出参考:指针的大小

为了实现多态,编译器首先要为每个多态类创建一张虚表(VTABLE),表中记录了这个类的所有虚函数的入口地址。此外,编译器还在每一个多态类的对象中设置了一个虚指针(Virtual Pointer/VPTR),它指向了该类的虚表(VTABLE)。

 

4. 虚析构函数 

考察下述代码:

//normal-destructor.cpp#include <iostream>class X {
public:X() {std::cout << "X()" << std::endl;}~X() {std::cout << "~X()" << std::endl;}
};class Y : public X {
public:Y() {std::cout << "Y()" << std::endl;}~Y() {std::cout << "~Y()" << std::endl;}
};int main() {X *p = new Y;delete p;return 0;
}

输出结果:

X()
Y()
~X()

问题:这个对象没有完全被拆除

解决:设置父类的析构函数为虚函数

因为子类和父类占据的内存不一致,因此父类的析构函数不能被继承。

修正后:

class X {
public:X() {std::cout << "X()" << std::endl;}virtual ~X() {std::cout << "~X()" << std::endl;}
};

 

四、纯虚函数和抽象类

1. 纯虚函数 

public:poly(std::string _ids = "poly", size_t e = 0) : ids(_ids), edge(e) {}~poly() {}std::string what() const {return ids;}virtual double area() const = 0;
};

2. 抽象类 

// 狭义:只有类型定义和纯虚函数,广义:凡是拥有纯虚函数的类
struct container {using value_type = ::value_type;using pointer = value_type*; using reference = value_type&;virtual bool empty() const = 0;
};
http://www.dtcms.com/wzjs/36885.html

相关文章:

  • 深圳设计总院武汉seo价格
  • 网站便宜建设中国网民博客 seo
  • 小的电商网站云南网站建设百度
  • 湖南网站建设案例建站系统哪个比较好
  • 鸿鹄网站建设太原网络推广公司
  • 如何做微信收费视频网站网站排名靠前方法
  • 江西省赣州市有什么好玩的地方seo最新技巧
  • 网站广告图片在线制作百度热度
  • 网络规划设计师历年试题分析与解答深圳搜索排名优化
  • 金融类的网站怎么做sem是什么的缩写
  • 版面设计网站免费发帖平台
  • 技术支持 长沙网站建设-创研科技口碑营销ppt
  • 网站建设绩效考核方案ppt推广自己产品的文案
  • wordpress推特登陆西安排名seo公司
  • 中国建设网站简州新城土地整改项目营销推广方案设计
  • 建设门户网站需要注意什么专门做推广的公司
  • 网站搭建后怎么操作seo链接优化建议
  • wordpress评论表情不显示不出来seo怎么刷关键词排名
  • 运输房产网站建设网络热词2023流行语及解释
  • 泰安企业建站公司哪里找郑州做网站哪家好
  • 做网站年赚千万竞价推广是做什么的
  • 网站建设可以网上兼职吗企业网站
  • 优秀网站建设模板百度推广登陆平台
  • 做外贸网站外包培训班有哪些
  • 网站建设的目的奖券世界推广网站
  • 中山推广网站关键词排名关键词优化
  • 如何对网站进行改版免费手机网页制作
  • 定制型网站一般价格产品的推广及宣传思路
  • 哪个网站专门做高清壁纸朋友圈营销广告
  • 东莞seo网站建设公司seo课程总结