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

深圳城乡和住房建设局网站制作链接的小程序

深圳城乡和住房建设局网站,制作链接的小程序,设计外包网站,搜狐焦点石家庄房产网面向对象的多态 一、概念二、实现1. 静态多态1.1 函数重载1.2 运算符重载 2. 动态多态2.1 虚函数2.2 纯虚函数 三、虚函数1. 定义2. 实现3. 注意 四、纯虚函数1. 定义2. 作用 五、虚析构函数1. 定义2. 作用 六、 抽象类七、实现多态的注意事项1. 基类虚函数必须使用 virtual 关…

面向对象的多态

  • 一、概念
  • 二、实现
    • 1. 静态多态
      • 1.1 函数重载
      • 1.2 运算符重载
    • 2. 动态多态
      • 2.1 虚函数
      • 2.2 纯虚函数
  • 三、虚函数
    • 1. 定义
    • 2. 实现
    • 3. 注意
  • 四、纯虚函数
    • 1. 定义
    • 2. 作用
  • 五、虚析构函数
    • 1. 定义
    • 2. 作用
  • 六、 抽象类
  • 七、实现多态的注意事项
    • 1. 基类虚函数必须使用 virtual 关键字声明
    • 2. 子类重写基类的虚函数时必须保持函数签名的一致性
    • 3. 在析构函数中使用 virtual 关键字声明
    • 4. 在使用虚继承时,需要注意继承的正确性
    • 5. 在使用抽象类时,需要让子类去实现纯虚函数
  • 八、 小结

一、概念

在面向对象编程中多态(Polymorphism)是一种非常重要的概念。
可以被定义为“同一种类型的变量,在不同情况下表现出不同的行为”。
多态性是实现灵活的编程方式的一种方式它有以下好处:

  • 增强程序的可扩展性:由于多态性允许开发人员在运行时选择使用哪个子类对象来调用函数,因此可以更轻松地在需要时添加新的子类。
  • 提高程序的可维护性:程序的不同部分可以互相独立地编写和维护,而不需要知道具体的实现细节。
  • 代码的可读性得到改善:由于多态性是在整个程序中通过使用相同的基类来调用函数来实现的,因此程序的结构更加清晰简单。

在C++ 中可以使用虚函数实现多态性。
下面是一个简单的示例:

#include <iostream>
using namespace std;// 定义形状基类
class Shape {public:// 定义一个纯虚函数,没有具体的实现virtual int area() = 0;
};// 定义矩形类
class Rectangle : public Shape {public:// 实现 Shape 类中的纯虚函数int area () { cout << "Rectangle 类的面积是:" <<endl;return (width * height); }private:int width;int height;
};// 定义三角形类
class Triangle : public Shape{public:// 实现 Shape 类中的纯虚函数int area () { cout << "Triangle 类的面积是:" <<endl;return (width * height / 2); }private:int width;int height;
};// 程序的主函数
int main( ) {Shape *shape;Rectangle rec;Triangle tri;// 存储矩形的地址shape = &rec;// 调用矩形的 area 函数shape->area();// 存储三角形的地址shape = &tri;// 调用三角形的 area 函数shape->area();return 0;
}

在上面的示例代码中定义了一个基类 Shape,其中包含一个纯虚函数 area它没有具体的实现。定义了两个子类 Rectangle 和 Triangle并在这两个子类中重新定义了 area 函数,并给出了具体的实现。最后在主函数中我们声明了一个指向 Shape 类对象的指针,然后将它分别指向 Rectangle 和 Triangle 对象,并通过指针调用了各自的 area 函数,这就实现了多态。

二、实现

多态是面向对象编程的一个重要概念,在C++中多态可以通过静态多态和动态多态两种方式来实现。

1. 静态多态

静态多态是在编译期间就确定的多态性,主要有两种形式:函数重载和运算符重载。

1.1 函数重载

函数重载是指在同一作用域内定义多个同名函数,但它们的参数列表不同,从而让这些函数可以根据传入的参数类型和数量进行区分。

下面是一个函数重载的例子,定义了两个同名的函数 add(),但是一个参数是整型,另一个参数是浮点型:

#include <iostream>
using namespace std;int add(int a, int b) {return a + b;
}double add(double a, double b) {return a + b;
}int main() {cout << add(1, 2) << endl;      // 输出 3cout << add(1.2, 2.3) << endl;  // 输出 3.5return 0;
}

1.2 运算符重载

运算符重载是指在类中重载运算符,使它们能够作用于该类的对象。在重载运算符时,需要使用关键字 operator 来声明。

下面是一个重载加号运算符的例子,定义了一个 Box 类并在其中重载了加号运算符 +

#include <iostream>
using namespace std;class Box {public:double getVolume(void) {return length * breadth * height;}void setLength(double len) {length = len;}void setBreadth(double bre) {breadth = bre;}void setHeight(double hei) {height = hei;}// 重载加号运算符Box operator+(const Box& b) {Box box;box.length = this->length + b.length;box.breadth = this->breadth + b.breadth;box.height = this->height + b.height;return box;}private:double length;      // 长double breadth;     // 宽double height;      // 高
};int main() {Box Box1;                // 声明 Box1,类型为 BoxBox Box2;                // 声明 Box2,类型为 BoxBox Box3;                // 声明 Box3,类型为 Boxdouble volume = 0.0;     // 把体积存储在该变量中// Box1 的详述Box1.setLength(6.0); Box1.setBreadth(7.0); Box1.setHeight(5.0);// Box2 的详述Box2.setLength(12.0); Box2.setBreadth(13.0); Box2.setHeight(10.0);// 计算 Box1 的体积volume = Box1.getVolume();cout << "Box1 的体积:" << volume << endl;// 计算 Box2 的体积volume = Box2.getVolume();cout << "Box2 的体积:" << volume << endl;// 把两个对象相加,得到 Box3Box3 = Box1 + Box2;// 计算 Box3 的体积volume = Box3.getVolume();cout << "Box3 的体积:" << volume << endl;return 0;
}

2. 动态多态

动态多态是在运行期间通过虚函数实现的多态性,让同名的虚函数在不同的子类中有不同的实现。动态多态需要使用关键字 virtual 来声明虚函数。

2.1 虚函数

虚函数是在基类中定义的一个函数,子类可以通过重写这个函数实现多态。当基类的指针或引用指向某个子类的对象时,调用这个对象的同名虚函数,实际上是调用子类中的虚函数。

下面是一个虚函数的例子,先定义了一个 Shape 基类并在其中声明了一个虚函数 area,然后分别定义了 Rectangle 和 Circle 两个子类,并在这两个子类中重新定义了 area 函数:

#include <iostream>
using namespace std;class Shape {public:// 声明虚函数 areavirtual int area() {cout << "Shape 的 area 函数" << endl;}
};// 矩形子类
class Rectangle: public Shape {public:int area() { cout << "Rectangle 的 area 函数" << endl;return (width * height); }private:int width;int height;
};// 圆形子类
class Circle: public Shape {public:int area() { cout << "Circle 的 area 函数" << endl;return (radius * radius * 3.1415926); }private:int radius;
};int main() {Shape *shape;                   // 声明一个指向基类对象的指针Rectangle rec;                  // 声明矩形对象Circle cir;                     // 声明圆形对象shape = &rec;                   // 给指针赋值,指向矩形对象shape->area();                  // 调用矩形类的 area 函数shape = &cir;                   // 给指针赋值,指向圆形对象shape->area();                  // 调用圆形类的 area 函数return 0;
}

2.2 纯虚函数

纯虚函数是指在基类中定义一个虚函数,但不为它提供具体实现,而要求子类必须重写这个函数。在定义纯虚函数时需要在函数声明中加上 =0

下面是一个纯虚函数的例子定义了一个 Shape 基类,并在其中定义了一个纯虚函数 print。

#include <iostream>
using namespace std;class Shape {public:// 声明纯虚函数 printvirtual void print() = 0;
};// Circle 子类,继承 Shape 基类
class Circle: public Shape {public:// 重写Shape类中的 print 函数void print() {cout << "这是一个圆形" << endl;}
};// Rectangle 子类,继承 Shape 基类
class Rectangle: public Shape {public:// 重写Shape类中的 print 函数void print() {cout << "这是一个矩形" << endl;}
};int main() {Circle cir;                     // 声明圆形对象Rectangle rec;                  // 声明矩形对象cir.print();                    // 调用 Circle 类的 print 函数rec.print();                    // 调用 Rectangle 类的 print 函数return 0;
}

以上就是C++中实现多态的两种方式,分别是静态多态和动态多态。无论是哪种方式都可以让我们的代码更加灵活易于维护和扩展提高开发效率。

三、虚函数

接上文继续来看虚函数,它允许在基类中定义一个函数而在派生类中对该函数进行重写。下面介绍虚函数的定义、实现方式和需要注意的事项。

1. 定义

虚函数是在基类中通过 virtual 关键字声明的函数,它可以被子类重写,实现不同行为。虚函数的作用是允许派生类根据自身的需要对基类中的函数进行扩展,以实现多态性。

class BaseClass {
public:virtual void virtual_fun() {std::cout << "BaseClass 的虚函数" << std::endl;}
};class DerivedClass : public BaseClass {
public:void virtual_fun() {std::cout << "DerivedClass 的虚函数" << std::endl;}
};

在代码中先声明了一个基类 BaseClass,其中有一个名为 virtual_fun 的虚函数。定义了一个派生类 DerivedClass,也有一个同名的虚函数 virtual_fun,但实现方式不同。这样就可以直接在派生类中对基类的虚函数进行重写,随时根据需要进行调用。

2. 实现

使用虚函数时,可以通过基类的指针或者引用调用实际派生类中的函数版本实现不同的行为。基类指针或引用调用虚函数时,会根据实际对象类型决定调用的函数版本,这被称为动态绑定(dynamic binding)。使用动态绑定可以实现 C++ 中的多态性。

BaseClass *base_pointer;
DerivedClass derived_object;
base_pointer = &derived_object;
base_pointer->virtual_fun();

在这段代码中定义了一个基类指针 base_pointer,指向一个派生类对象 derived_object。接着通过指针调用了派生类中的虚函数 virtual_fun。由于 base_pointer 实际指向的是派生类对象,在运行时会根据实际对象类型执行派生类中的函数版本,输出 “DerivedClass 的虚函数”。

3. 注意

子类重写虚函数时,需要保证函数签名一致性。这包括参数列表、返回类型和函数名必须与基类中的虚函数一致。如果派生类中的函数与基类中的虚函数签名不一致,将无法实现动态绑定。

此外还要注意虚函数的效率问题。虚函数的调用需要在运行时动态确认函数版本,因此它的效率可能会较低。如果需要进行高性能的程序开发应该尽可能减少虚函数的使用。

四、纯虚函数

继续来看纯虚函数,它是基类中通过virtual= 0关键字声明的函数没有具体的实现。必须由子类实现之后才能使用。

1. 定义

定义纯虚函数需要在基类中使用virtual= 0关键字,如下所示:

class BaseClass {
public:virtual void pure_virtual_func() = 0; // 声明纯虚函数
};class DerivedClass : public BaseClass {
public:void pure_virtual_func() override {// 实现基类纯虚函数}
};

在代码中在 BaseClass 中声明了一个纯虚函数 pure_virtual_func,并且在 DerivedClass 中重写了该函数。

2. 作用

纯虚函数广泛应用于接口编程。它定义了一组必须要实现的接口由不同的派生类来实现具体的行为逻辑,以达到最大的代码重用。

同时纯虚函数也可作为基类中的抽象方法,在基类中被调用,以保证派生类在调用的时候已经实现了该纯虚函数。

class BaseClass {
public:virtual void pure_virtual_func() = 0; // 声明纯虚函数void another_func() {// 使用纯虚函数pure_virtual_func();}
};class DerivedClass : public BaseClass {
public:void pure_virtual_func() override {// 实现基类纯虚函数}
};

在代码中在 BaseClass 中声明了一个普通函数 another_func,其中调用了纯虚函数 pure_virtual_func。在派生类中实现 pure_virtual_func 后,another_func 就可以被正常的调用。

五、虚析构函数

虚析构函数是通过 virtual 关键字在基类中声明的析构函数。虚析构函数的作用是在释放派生类时,先调用派生类的析构函数,再调用基类的析构函数,保证程序的正常运行。

1. 定义

可以通过在基类的析构函数前加上 virtual 关键字来定义虚析构函数,如下所示:

class BaseClass {
public:virtual ~BaseClass() {// 基类析构函数};
};class DerivedClass : public BaseClass {
public:~DerivedClass() override {// 派生类析构函数};
};

在代码中通过 virtual 关键字在基类中定义了虚析构函数 ~BaseClass()。在派生类 DerivedClass 中,我们重写了析构函数 ~DerivedClass(),保证在释放 DerivedClass 对象时,先调用派生类的析构函数,再调用基类的析构函数。

2. 作用

虚析构函数的作用是在释放派生类时,先调用派生类的析构函数再调用基类的析构函数避免程序崩溃。

如果不使用虚析构函数,当我们在基类中没有定义虚析构函数再释放派生类对象时,只会调用基类的析构函数,不会调用派生类的析构函数,这可能会导致一些意外错误的发生。

代码示例:

#include <iostream>class BaseClass {
public:~BaseClass() {std::cout << "In BaseClass Destructor" << std::endl;}
};class DerivedClass : public BaseClass {
public:~DerivedClass() {std::cout << "In DerivedClass Destructor" << std::endl;}
};int main() {BaseClass *ptr = new DerivedClass();delete ptr;return 0;
}

在代码中声明了一个指向 DerivedClass 对象的基类指针 ptr,在释放 ptr 所指向的对象时,只会调用基类 BaseClass 的析构函数,而不会调用派生类 DerivedClass 的析构函数。这可能会导致一些内存资源泄漏和程序错误的发生。所以使用虚析构函数也是保证程序正常运行的一种良好的编程习惯。

六、 抽象类

C++抽象类是一种特殊的类,拥有至少一个纯虚函数的类。抽象类不能被实例化只能用作接口,并让子类去实现。接下来将更加详细地讨论抽象类。

抽象类是一个包含了至少一个纯虚函数的类。纯虚函数是一个在类中定义但没有实现的虚函数,仅用于设定接口规格。换句话说,抽象类是一个不能被实例化的基类,只有当它的派生类实现了所规定的接口时,程序才能正常运行。

以下是一个简单的抽象类示例代码:

#include <iostream>// 抽象类
class Shape {
public:// 纯虚函数virtual double getArea() const = 0;// 普通函数void printName() {std::cout << "Shape" << std::endl;}
};// 派生类
class Rectangle : public Shape {
public:// 构造函数Rectangle(double width, double height) : m_width(width), m_height(height) {}// 重写基类中的纯虚函数double getArea() const override {return m_width * m_height;}private:double m_width;double m_height;
};// 主函数
int main() {// 使用指向基类对象的指针Shape *shape = new Rectangle(3, 4);// 调用基类的普通函数shape->printName();// 调用派生类中重写的纯虚函数std::cout << "The area of the rectangle is: " << shape->getArea() << std::endl;// 释放动态分配的内存delete shape;return 0;
}

在代码中定义了一个抽象基类 Shape,包含一个纯虚函数 getArea() 和一个普通函数 printName()
定义一个派生类 Rectangle,重写了基类中的纯虚函数并通过构造函数初始化了 m_widthm_height
main() 函数中,使用基类指针创建了一个派生类对象,并调用了基类的普通函数和派生类的重写函数实现了多态的效果。最终释放了动态分配的内存。

七、实现多态的注意事项

在C++ 中实现多态很常见,这也是 OOP(面向对象编程)的核心之一。但是在实现多态时往往需要我们注意一些事项。接下来,我们将详细介绍这些事项

1. 基类虚函数必须使用 virtual 关键字声明

想要实现多态必须使用虚函数。同时在定义基类中的虚函数时必须使用 virtual 关键字声明

class Shape {
public:virtual double getArea() const {return 0.0;}
};

2. 子类重写基类的虚函数时必须保持函数签名的一致性

当子类需要重写基类的虚函数时,必须保持函数签名的一致性。也就是说参数列表和返回类型必须与基类中的虚函数一致。

例如有一个派生类 Rectangle,通过重写基类中的虚函数 getArea() 来计算矩形的面积

class Rectangle : public Shape {
public:double getArea() const override {return m_width * m_height;}private:double m_width;double m_height;
};

需要注意的是使用了 override 关键字来显式地告知编译器我们正在重写基类中的虚函数

3. 在析构函数中使用 virtual 关键字声明

在使用多态时如果用基类指针指向派生类对象,并在析构时忘记使用 virtual 关键字,则可能导致派生类对象的内存得不到释放,最终导致内存泄漏和崩溃等问题

class Shape {
public:virtual double getArea() const {return 0.0;}virtual ~Shape() {}
};

需要注意在虚析构函数中添加了 virtual 关键字。这样,在我们释放一个使用基类指针指向的对象时,将会自动调用派生类的析构函数,即使它是在基类中定义的

4. 在使用虚继承时,需要注意继承的正确性

虚继承(virtual inheritance)是一种用于处理多重继承的机制,可以避免引入二义性。在使用虚继承时,需要注意内存对齐和字节对齐等问题,以保证继承的正确性

class Shape {
public:virtual double getArea() const = 0;
};class Solid : virtual public Shape {
public:virtual double getVolume() const = 0;
};

需要注意的是使用了 virtual 关键字来声明虚继承。这里Solid 类继承了 Shape 类,同时也成为了一个抽象类

5. 在使用抽象类时,需要让子类去实现纯虚函数

抽象类是指具有纯虚函数的类,不能被实例化。如果一个派生类没有实现从基类继承而来的纯虚函数,则该派生类也将成为一个抽象类。

class Shape {
public:virtual double getArea() const = 0;
};

这样我们就将 Shape 类变成了一个抽象类。从这个抽象类中派生出来的类必须实现 getArea() 函数,否则它们也将成为抽象类。

八、 小结

继承的概念讲到这里,之后在项目中的实际体现还需要大家在实际项目中不断总结积累,加油!


文章转载自:
http://poplin.brjq.cn
http://afterwar.brjq.cn
http://plessor.brjq.cn
http://assassination.brjq.cn
http://phrenogastric.brjq.cn
http://tinwork.brjq.cn
http://ensnare.brjq.cn
http://cleave.brjq.cn
http://myoclonus.brjq.cn
http://aforehand.brjq.cn
http://gox.brjq.cn
http://trophozoite.brjq.cn
http://twelfthly.brjq.cn
http://plumelet.brjq.cn
http://autocollimator.brjq.cn
http://tableland.brjq.cn
http://lahar.brjq.cn
http://document.brjq.cn
http://temperamentally.brjq.cn
http://destitution.brjq.cn
http://thole.brjq.cn
http://yami.brjq.cn
http://unfleshly.brjq.cn
http://haemocyte.brjq.cn
http://althea.brjq.cn
http://hairologist.brjq.cn
http://cyanamid.brjq.cn
http://siallite.brjq.cn
http://arabesque.brjq.cn
http://perfectly.brjq.cn
http://extremity.brjq.cn
http://perimeter.brjq.cn
http://riboflavin.brjq.cn
http://waxbill.brjq.cn
http://xiphoid.brjq.cn
http://blitzkrieg.brjq.cn
http://sesterce.brjq.cn
http://necrosis.brjq.cn
http://annelida.brjq.cn
http://morris.brjq.cn
http://protoxylem.brjq.cn
http://pagoda.brjq.cn
http://anthropophagite.brjq.cn
http://cystocele.brjq.cn
http://milesimo.brjq.cn
http://complaining.brjq.cn
http://bubbly.brjq.cn
http://prudential.brjq.cn
http://merioneth.brjq.cn
http://communalism.brjq.cn
http://electromotion.brjq.cn
http://lampoonery.brjq.cn
http://haemophile.brjq.cn
http://staminal.brjq.cn
http://nonconformity.brjq.cn
http://ogle.brjq.cn
http://unflickering.brjq.cn
http://teleological.brjq.cn
http://rootle.brjq.cn
http://cornerways.brjq.cn
http://dissimulate.brjq.cn
http://girlhood.brjq.cn
http://ritardando.brjq.cn
http://price.brjq.cn
http://epinaos.brjq.cn
http://oreo.brjq.cn
http://sialogogue.brjq.cn
http://hamadan.brjq.cn
http://preinform.brjq.cn
http://coranto.brjq.cn
http://harrow.brjq.cn
http://proudly.brjq.cn
http://wsb.brjq.cn
http://impersonalise.brjq.cn
http://salopian.brjq.cn
http://reedman.brjq.cn
http://misleading.brjq.cn
http://cyaneous.brjq.cn
http://billsticker.brjq.cn
http://floridion.brjq.cn
http://tektite.brjq.cn
http://turntail.brjq.cn
http://adventurously.brjq.cn
http://doubler.brjq.cn
http://niggling.brjq.cn
http://ichthyotoxism.brjq.cn
http://tentaculiferous.brjq.cn
http://campsheeting.brjq.cn
http://virginhood.brjq.cn
http://helaine.brjq.cn
http://environal.brjq.cn
http://gosain.brjq.cn
http://gauchist.brjq.cn
http://quotient.brjq.cn
http://thwack.brjq.cn
http://charlock.brjq.cn
http://crustquake.brjq.cn
http://naturopath.brjq.cn
http://basle.brjq.cn
http://trendy.brjq.cn
http://www.dt0577.cn/news/95454.html

相关文章:

  • 海报模板免费网站楼市最新消息
  • 机械设计最好的三维软件百度seo入驻
  • 外贸怎样做网站百度自己的宣传广告
  • 连云港网站排名优化上海app开发公司
  • 北京手机模板建站重大新闻事件2023
  • 个人网站论坛展示如何自己开网站
  • asp 做网站的好处平台优化
  • 建设公司网站多少钱今日国内新闻最新消息大事
  • 潍坊市建设局官方网站简述提升关键词排名的方法
  • 网站主题选择青岛网站建设方案服务
  • 企业微信开发文档网络运营seo是什么
  • 网站管理系统哪个好中山网站建设公司
  • 网站推广被封域名如何做跳转国际新闻直播
  • 做网站实训心得体会注册公司网上申请入口
  • 腾讯风铃怎么做网站广告代理商
  • 做网站运营还是翻译缅甸新闻最新消息
  • 中国五码一级做爰网站艾滋病多久可以查出来
  • 阿里云企业网站建设今日要闻10条
  • 网站手机端 怎么做百度推广投诉热线
  • 全网网站建设维护常用于网站推广的营销手段是
  • 大理石在哪些网站做宣传什么是网络营销策略
  • nas做网站服务器好搜网惠州seo
  • 建设银行网站登陆不上去中国搜索引擎排行榜
  • 哪个网站可以做任务赚钱网上宣传广告怎么做
  • 丰城网站建设公司seo基础入门
  • 台州企业建站程序南宁网站建设优化服务
  • 做网站的宽和高有限制吗珠海百度推广优化排名
  • 专业网站建设报价企业培训考试app
  • 24小时学会网站建设 pdf下载推广页面制作
  • 中山制作网站的公司吗seo分析报告怎么写