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

网站建设规划方案.ppt/汕头seo计费管理

网站建设规划方案.ppt,汕头seo计费管理,网络广告视频,wordpress 前台上传图片今天,带来C多态的讲解。 多态和继承并用,能产生“魔法般的效果”。 *文中不足错漏之处望请斧正! 见见多态 是什么 使得父类指针或引用有多种形态。 怎么使它有多种形态呢?咱们先见见猪跑。 见见猪跑 class Base { public:v…

今天,带来C++多态的讲解。

多态和继承并用,能产生“魔法般的效果”。

*文中不足错漏之处望请斧正!


见见多态

是什么

使得父类指针或引用有多种形态。

怎么使它有多种形态呢?咱们先见见猪跑。

见见猪跑

class Base
{
public:virtual void print() { cout << "Base" << endl;}
};class Derive1 : public Base
{
public:virtual void print() { cout << "Derive1" << endl;}
};class Derive2 : public Base
{
public:virtual void print() { cout << "Derive2" << endl;}
};int main()
{Base b;Derive1 d1;Derive2 d2;Base* ptr;ptr = &b;ptr->print();ptr = &d1;ptr->print();ptr = &d2;ptr->print();return 0;
}
Base
Derive1
Derive2

父类指针,存父类对象地址,就能调用父类中的print,存子类对象地址,就能调用子类中的print,拥有了多种形态。


多态的实现

满足多态的前提:子类对父类的虚函数完成重写。

啥是虚函数,啥是重写?

虚函数

虚函数是被virtual修饰的成员函数。可以理解为一种对函数体的泛化。

在声明虚函数的域,默认有一份实例;在此域之外,你可以对虚函数“实例化”,得到新的一份实例。

其作用是实现多态性。

重写/覆盖

重写就是“实例化”虚函数,可以产生新的“虚函数实例”,会把原来的实例覆盖掉。

  • 对虚函数重写的条件:[函数名、返回值、参数]和父类的虚函数相同
  • *重写的仅仅是函数体,重写前后接口是一样的
  • 例外
    • 子类的虚函数可以不写virtual
    • 协变:返回值可以是任意父子类关系的指针/引用
class Base
{
public:virtual void print() { cout << "Base" << endl;} 
};class Derive1 : public Base
{
public:virtual void print() { cout << "Derive1" << endl;}
};class Derive2 : public Base
{
public:virtual void print() { cout << "Derive2" << endl;}
};
int main()
{Base b;Derive1 d1;Derive2 d2;Base* ptr;ptr = &b;ptr->print();ptr = &d1;ptr->print();ptr = &d2;ptr->print();return 0;
}
  • print这个虚函数默认有一份实例,它的函数体功能是打印"Base"的
  • print这个虚函数在Derive1中被重写了,这份新的实例把原来默认的覆盖了,它的函数体功能是打印”Derive1”的
  • print这个虚函数在Derive2中被重写了,这份新的实例把原来默认的覆盖了,它的函数体功能是打印”Derive2”的

如果不重写呢?

class Base
{
public:virtual void print() { cout << "Base" << endl;}
};class Derive1 : public Base
{
public:
//    virtual void print() { cout << "Derive1" << endl;}
};class Derive2 : public Base
{
public:
//    virtual void print() { cout << "Derive2" << endl;}
};

main函数不变,结果如下:

Base
Base
Base

看上面这个调用的手法,有个疑问:它是怎么知道调用哪个虚函数的实例的?

这就要说到虚函数表了。

虚函数表

有虚函数的类,其对象都会存一个虚函数表指针vptr,虚函数表vtable是干嘛的?

虚函数表是一个类的虚函数地址表,存放了这个类对某个虚函数的所有实例(对虚函数进行重写的到的真实函数)的地址。说白了,某个类对一个虚函数的实例,是用虚函数表来描述和组织起来的。

  • 为提高效率,这个可能高频访问的虚表(虚函数表)指针一般放在对象的头4/8个字节
  • 按我们的说法,虚函数表描述的是整个类对某个虚函数的实例,因此它就像类的static成员一样,属于整个类,所以存放在代码段

大概过程:

  1. 创建类对象(对象的头4/8个字节存了一个虚表指针)
  2. 调用对象的某个虚函数实例
  3. 根据虚表来找到当前类对这个虚函数的实例

普通调用和多态调用

普通调用也叫静态绑定,多态调用也叫动态绑定。

静态绑定:编译时通过调用方类型确定调用的函数
动态绑定:运行时通过父类指针指向的对象类型确定调用的函数

  • 用父类指针或引用调用被重写的虚函数是动态绑定
  • 其他都是静态绑定

在这里插入图片描述


多态中的析构函数

若在继承中出现这样的情况:

  1. 动态申请对象
  2. 子类没有重写析构函数(静态绑定)

则delete动态对象的空间时,析构调用不完全——只会根据指针类型静态绑定,只调用父类的析构。

class Base
{
public:~Base(){cout << "~Base()" << endl;delete[] _pb;}
private:int* _pb = new int[10];
};class Derive : public Base
{
public:~Derive(){cout << "~Derive()" << endl;delete[] _pd;}
private:int* _pd = new int[20];
};int main()
{Base* ptr = new Derive;delete ptr;
}
~Base()

可以看到,只会调用父类析构。

静态绑定不行,我们来动态绑定,多态上场。

class Base
{
public:virtual ~Base(){cout << "~Base()" << endl;delete[] _pb;}
private:int* _pb = new int[10];
};class Derive : public Base
{
public:~Derive() //此处可以不用写virtual,这是子类可以不用写virtual的一种使用场景{cout << "~Derive()" << endl;delete[] _pd;}
private:int* _pd = new int[20];
};int main()
{Base* ptr = new Derive;delete ptr;
}
~Derive()
~Base()

满足了多态,调用完父类析构之后就会自动调用子类析构,成功解决。

Destructor

我们之前提到继承中的析构函数名都会被处理成Destructor,为了能够满足重写的条件。

在这里插入图片描述


继承中的对象模型

  1. 单继承(无重写)的虚函数表:
    1. 虚函数按照其声明顺序放于表中
    2. 父类的虚函数在子类的虚函数前面
  2. 单继承(有重写)的虚函数表
    1. 被重写的虚函数被放到了虚表中原来父类虚函数的位置(所以调用的时候不会跑去调用父类的,而是调用自己的)
    2. 没有被覆盖的函数依旧
  3. 多继承(无重写)的虚函数表
    1. 每个父类都有自己的虚表
    2. 子类的成员函数被放到了第一个父类的表中(所谓的第一个父类是按照声明顺序来判断的)

final和override

final

表明类不能被继承。

设计一个不能被继承的类

  1. final修饰类
class A final {};class B : public A {};int main()
{B b; //A被final修饰,无法被继承return 0;
}
  1. 构造私有化——子类想实例化必须调用父类构造。
class A
{
private:A() {}
};class B : public A {};int main()
{B b; //A的构造是私有,实例B需要调用A的析构,调不动,所以A无法被继承return 0;
}

override

override可以检查子类虚函数是否和父类的某个虚函数构成重写,或者强制要求某个函数被重写(需要重写的就都带上)。

//override:检查子类的虚函数是否完成重写
class Car
{
public:void Drive() {}
};class Benz : public Car
{
public://err:'Drive' marked 'override' but does not override any member functionsvirtual void Drive() override { cout << "Benz->comfortable" << endl; }
};int main()
{Benz mycar;mycar.Drive();return 0;
}

抽象类

先导:纯虚函数

是什么:虚函数后写上0,不需要函数体的虚函数。(可以有函数体,但不会被执行)

virtual void func() = 0;

是什么

有纯虚函数的类。

为什么

用于接口继承。

  • 接口继承:主要是为了让子类重写,形成多态
  • 实现继承:主要是为了复用函数体
class Car
{
public:virtual void Drive() = 0;
};class BMW : public Car
{
public:virtual void Drive(){cout << "驾驶乐趣+1" << endl;}
};int main()
{BMW mycar;mycar.Drive();return 0;
}

特性

  • 抽象类不能实例化出对象
  • 若想实例化对象,必须重写纯虚函数(这样就不是抽象类了)
  • 子类继承了抽象类也还是抽象类

今天的分享就到这里了,感谢您能看到这里。

这里是培根的blog,期待与你共同进步!

http://www.jmfq.cn/news/5229811.html

相关文章:

  • 免费做网站建设/海南seo排名优化公司
  • 威宁住房和城乡建设局网站/百度推广服务
  • 网站制作知识/怎样开自己的网站
  • 新手什么网站做外贸/常见的推广平台有哪些
  • 前程无忧招聘网站标记怎么做/企业培训网
  • 哪个网站可以做抑郁症测试题/论文收录网站排名
  • 网站开发出来有后台么/谷歌app下载
  • wordpress 微信图标/网站内容优化关键词布局
  • 国学大师网站谁做的/北京网络推广公司wyhseo
  • 湖南高端网站制作公司/360手机优化大师下载
  • 建站公司转型做什么业务/宜昌今日头条新闻
  • 做网站有哪些费用/志鸿优化网
  • org已经备案的网站/网络营销案例分析题
  • 最专业的网站建设/google移动服务应用优化
  • 长安网站建设制作/媒体营销
  • 男人做爽的免费网站/抖音seo培训
  • 网站商城建设/合肥优化排名推广
  • 做网站开发的公司哪家好/百度移动版
  • 百度网站公司信息推广怎么做/软件开发培训班
  • 怎么把做的网站传/seo权威入门教程
  • 傻瓜做网站软件/搜索引擎营销ppt
  • 公司的网站如何进行修改布局/关于营销的最新的新闻
  • 西安知名网站推广/朝阳区seo技术
  • 云空间搭建网站/seo线下培训班
  • 成都市住房和城乡建设厅官网/南京网站设计优化公司
  • 我做网站/seo软件系统
  • 找人做网站推广/常州网站优化
  • 怎么做网站收录/个人网站免费制作平台
  • 网站没有地图怎么做/百度公司图片
  • 企业问题及解决方案/优化大师win10下载