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

网站建设招标模板风中有朵雨做的云网站观看

网站建设招标模板,风中有朵雨做的云网站观看,互联网怎么打广告推广,哪些是企业网站目录 一、多态的概念和虚函数 1.1 - 用基类指针指向派生类对象 1.2 - 虚函数和虚函数的重写 1.3 - 多态构成的条件 1.4 - 多态的应用场景 二、协变和如何析构派生类对象 2.1 - 协变 2.2 - 如何析构派生类对象 三、C11 的 override 和 final 关键字 一、多态的概念和虚…

目录

一、多态的概念和虚函数

1.1 - 用基类指针指向派生类对象

1.2 - 虚函数和虚函数的重写

1.3 - 多态构成的条件

1.4 - 多态的应用场景

二、协变和如何析构派生类对象

2.1 - 协变

2.2 - 如何析构派生类对象

三、C++11 的 override 和 final 关键字


 


一、多态的概念和虚函数

1.1 - 用基类指针指向派生类对象

基类指针可以指向派生类对象,但是通过基类指针只能使用基类的成员(包括成员变量和成员函数),不能使用派生类的成员

#include <iostream>
using namespace std;
​
class Person
{
public:Person(const char* name = "张三", int age = 18): _name(name), _age(age){ }
​void Print() const{cout << _name << "今年" << _age << "岁了。" << endl;}
protected:string _name;int _age;
};
​
class Student : public Person
{
public:Student(const char* name = "张三", int age = 18, int id = 0): Person(name, age), _id(id){ }
​void Print() const{cout << _name << "今年" << _age << "岁了,学号是" << _id << "。" << endl;}
protected:int _id; 
};
​
int main()
{Person p("李四", 19);Person* pp = &p;pp->Print();  // 李四今年19岁了。Student s("王五", 20, 2);pp = &s;pp->Print();  // 王五今年20岁了。return 0;
}

1.2 - 虚函数和虚函数的重写

如果在基类的成员函数前面加上 virtual 关键字,把它声明为虚函数,并且在派生类中对基类的虚函数进行重写(覆盖),那么当基类指针指向派生类对象时,就可以调用派生类中同名的成员函数,通过派生类中同名的成员函数,也就可以访问派生类对象的成员变量

当派生类中有一个跟基类完全相同的虚函数时,即派生类虚函数与基类虚函数的返回值类型、函数名、参数列表完全相同,就称派生类重写(覆盖)了基类的虚函数

#include <iostream>
using namespace std;
​
class Person
{
public:Person(const char* name = "张三", int age = 18): _name(name), _age(age){ }// 声明为虚函数virtual void Print() const{cout << _name << "今年" << _age << "岁了。" << endl;}
protected:string _name;int _age;
};
​
class Student : public Person
{
public:Student(const char* name = "张三", int age = 18, int id = 0): Person(name, age), _id(id){ }// 注意:在派生类中重写基类的虚函数时,派生类的虚函数可以不加 virtual 关键字,// 但是这种写法不是很规范,不建议这样操作。virtual void Print() const{cout << _name << "今年" << _age << "岁了,学号是" << _id << "。" << endl;}
protected:int _id;
};
​
int main()
{Person p("李四", 19);Person* pp = &p;pp->Print();  // 李四今年19岁了。Student s("王五", 20, 2);pp = &s;pp>->Print();  // 王五今年20岁了,学号是2。return 0;
}

有了虚函数,基类指针指向基类对象时就使用基类的成员函数,指向派生类对象时就使用派生类的成员函数,基类指针表现出了多种形态,这种现象我们称之为多态(Polymorphism)

1.3 - 多态构成的条件

通过以上的内容,可以总结出构成多态的条件

  1. 必须存在继承关系;

  2. 继承关系中派生类必须对基类的虚函数进行重写。

  3. 必须通过基类的指针或引用调用虚函数。

因为引用在本质上是通过指针的方式实现的,所以,既然借助基类指针可以实现多态,那么借助基类引用也可以实现多态

Person& rp = p;
p.Print();  // 李四今年19岁了。
Person& rs = s;
rs.Print();  // 王五今年20岁了,学号是2。

1.4 - 多态的应用场景

在应用开发中,我们可以在基类的成员函数中实现基本的功能,并且把基类的成员函数设置为虚函数,留给派生类去扩展和优化、实现个性化的功能

当然,要达到以上的目的,不一定要使用虚函数和多态,例如

#include <iostream>
using namespace std;
​
class Hero
{
public:void skillQ() { cout << "英雄释放了 Q 技能" << endl; }void skillW() { cout << "英雄释放了 E 技能" << endl; }void skillE() { cout << "英雄释放了 W 技能" << endl; }void skillR() { cout << "英雄释放了 R 技能" << endl; }
protected:int HP;  // 体力值、血量int MP;  // 魔法值int AD;  // 物理伤害int AP;  // 法术伤害
};
​
class A : public Hero
{
public:void skillQ() { cout << "英雄 A 释放了 Q 技能" << endl; }void skillW() { cout << "英雄 A 释放了 E 技能" << endl; }void skillE() { cout << "英雄 A 释放了 W 技能" << endl; }void skillR() { cout << "英雄 A 释放了 R 技能" << endl; }
};
​
class B : public Hero
{
public:void skillQ() { cout << "英雄 B 释放了 Q 技能" << endl; }void skillW() { cout << "英雄 B 释放了 E 技能" << endl; }void skillE() { cout << "英雄 B 释放了 W 技能" << endl; }void skillR() { cout << "英雄 B 释放了 R 技能" << endl; }
};
​
class C : public Hero
{
public:void skillQ() { cout << "英雄 C 释放了 Q 技能" << endl; }void skillW() { cout << "英雄 C 释放了 E 技能" << endl; }void skillE() { cout << "英雄 C 释放了 W 技能" << endl; }void skillR() { cout << "英雄 C 释放了 R 技能" << endl; }
};
​
int main()
{int option = 0;cout << "请选择英雄(1-A;2-B;3-C):";cin >> option;
​if (option == 1){A a;a.skillQ();a.skillW();a.skillE();a.skillR();}else if (option == 2){B b;b.skillQ();b.skillW();b.skillE();b.skillR();}else if (option == 3){C c;c.skillQ();c.skillW();c.skillE();c.skillR();}return 0;
}

但是使用多态可以让编程更方便,代码更精简

#include <iostream>
using namespace std;
​
class Hero
{
public:virtual void skillQ() { cout << "英雄释放了 Q 技能" << endl; }virtual void skillW() { cout << "英雄释放了 E 技能" << endl; }virtual void skillE() { cout << "英雄释放了 W 技能" << endl; }virtual void skillR() { cout << "英雄释放了 R 技能" << endl; }
protected:int HP;  // 体力值、血量int MP;  // 魔法值int AD;  // 物理伤害int AP;  // 法术伤害
};
​
class A : public Hero
{
public:virtual void skillQ() { cout << "英雄 A 释放了 Q 技能" << endl; }virtual void skillW() { cout << "英雄 A 释放了 E 技能" << endl; }virtual void skillE() { cout << "英雄 A 释放了 W 技能" << endl; }virtual void skillR() { cout << "英雄 A 释放了 R 技能" << endl; }
};
​
class B : public Hero
{
public:virtual void skillQ() { cout << "英雄 B 释放了 Q 技能" << endl; }virtual void skillW() { cout << "英雄 B 释放了 E 技能" << endl; }virtual void skillE() { cout << "英雄 B 释放了 W 技能" << endl; }virtual void skillR() { cout << "英雄 B 释放了 R 技能" << endl; }
};
​
class C : public Hero
{
public:virtual void skillQ() { cout << "英雄 C 释放了 Q 技能" << endl; }virtual void skillW() { cout << "英雄 C 释放了 E 技能" << endl; }virtual void skillE() { cout << "英雄 C 释放了 W 技能" << endl; }virtual void skillR() { cout << "英雄 C 释放了 R 技能" << endl; }
};
​
int main()
{int option = 0;cout << "请选择英雄(1-A;2-B;3-C):";cin >> option;
​Hero* p = nullptr;if (option == 1)p = new A;else if (option == 2)p = new B;else if (option == 3)p = new C;
​if (p){p->skillQ();p->skillW();p->skillE();p->skillR();delete p;}return 0;
}


二、协变和如何析构派生类对象

2.1 - 协变

协变就是在派生类中重写基类虚函数时,基类虚函数的返回值类型为基类对象的指针或引用,派生类虚函数的返回值类型为派生类对象的指针或引用

协变是虚函数重写的一种例外

class A {};
​
class B : public A {};
​
class Person
{
public:virtual A* func() { return new A; }
};
​
class Student : public Person
{
public:virtual B* func() { return new B; }
};

2.2 - 如何析构派生类对象

用基类指针指向派生类对象是多态的精髓,但是如果用基类指针销毁派生类对象的时候,不能调用派生类的析构函数,就可能会造成内存泄漏,因为在应用开发中,我们一般会把释放资源的代码写在析构函数中,例如释放堆区申请的内存空间

#include <iostream>
using namespace std;
​
class Person
{
public:~Person() { cout << "~Person()" << endl; }
};
​
class Student : public Person
{
public:~Student() { cout << "~Student()" << endl; }
};
​
int main()
{Person* pp = new Person;delete pp;  // ~Person()
​pp = new Student;delete pp;// ~Person() --> 说明没有调用派生类的析构函数return 0;
}

不过解决方法很简单,只要把基类的析构函数设置为虚函数,然后在派生类中重写基类的虚函数即可

但问题是基类和派生类的析构函数的函数名是不可能相同的,违背了虚函数重写的规则,答案则是 C++ 编译器对它们的名称做了特殊的处理,编译后统一处理成 destructor

#include <iostream>
using namespace std;
​
class Person
{
public:virtual ~Person() { cout << "~Person()" << endl; }
};
​
class Student : public Person
{
public:virtual ~Student() { cout << "~Student()" << endl; }
};
​
int main()
{Person* pp = new Person;delete pp;  // ~Person()
​pp = new Student;delete pp;// ~Student()// ~Person()return 0;
}


三、C++11 的 override 和 final 关键字

C++11 的 override 和 final 关键字能让我们的程序在继承类和重写虚函数时更安全,以及更清晰。

  1. override 关键字可以让编译器检查我们在派生类中重写的基类的虚函数是否正确

    class Person
    {
    public:virtual void func() const { cout << "hello world~" << endl; };
    };
    ​
    class Student : public Person
    {
    public:virtual void func() override { cout << "你好,世界~" << endl; };
    };

    这是因为我们在派生类中重写基类的虚函数时,忘记加 const

  2. final 关键字则可以防止派生类重写基类的虚函数

    class Person
    {
    public:virtual void func() const final { cout << "hello world~" << endl; }
    };
    ​
    class Student : public Person
    {
    public:virtual void func() const { cout << "你好,世界~" << endl; }
    };

http://www.yayakq.cn/news/442778/

相关文章:

  • 中国个人优秀网站手机网页素材
  • 甘肃系统建站怎么用安钢贴吧
  • 怀化网站定制做的系统怎么和网站对接
  • 江西建网站做优化珠海网络营销外包收费情况
  • 设计常去的网站合肥房地产最新消息
  • 义乌网站建设公司价位洛阳seo网站
  • cps推广是什么意思简述seo的概念
  • 淘宝做链接的网站网站的外部链接怎么做
  • 宝安做棋牌网站建设找哪家效益快网页设计模板加代码
  • 12306网站开发时间软件商城推荐
  • 网站站长在哪登陆后台义乌正规自适应网站建设首选
  • 中山网站制作系统建设人行官方网站下载
  • 电商网站建设的目标企业网站的模式
  • 站长工具查询网站兰州网站建设索王道下拉
  • 自学网站建设需要什么学历wordpress安装到子目录下
  • 怎样在设计网站做图赚钱吗六安市城乡建设网站
  • 电商运营 网站运营建设九九网站
  • 个人如果做网站赚钱吗网站建设公司权威机构
  • 网站更改机房备案山东企业
  • 哪个公司网站设计最好国外教做美食网站
  • 公司内部网站的作用网站建设收费明细表
  • 做电影网站为什么要数据库jsp鲜花网站开发源代码
  • 郴州微网站建设沈阳市建设工程信息网招标公告
  • 西安建筑公司网站建设主播网站怎么建立
  • 网站中的二维码设计嘉兴企业做网站
  • 程序员是不是都是做网站的怎么做企业管理软件定制
  • 番禺南村网站建设安康市网约车平台
  • 深圳企业品牌网站启动培训网站建设的请示
  • 建设部网站工程资质做网站推广要注意的事项
  • 怀安县建设局网站贵阳国家经济技术开发区门户网站