当前位置: 首页 > 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://www.jmfq.cn/news/5341627.html

相关文章:

  • 绿建设计院网站/站长网站工具
  • 优科技网站建设/网站关键词优化费用
  • 中学网站建设/友链之家
  • 龙华三网合一网站建设/买域名要多少钱一个
  • 厦门市建设管理协会网站首页/百度客服中心电话
  • 建设学校网站前的需求分析/优化推广网站排名
  • 房地产网站建设方案/万秀服务不错的seo推广
  • 网站建设费记在什么科目下/自媒体是如何赚钱的
  • 西安道桥建设有限公司网站/想要网站导航推广页
  • 建设银行网上银行网站/优化大师在哪里
  • 南宁市网站建设公司/百度网盘怎么提取别人资源
  • 四川网站建设开发/营销公关
  • 句容网站建设/郑州seo外包v1
  • 朝阳建设委员会网站/seo实战密码电子版
  • 微网站建设申请/自动点击器
  • 营销网站建设哪家便宜/无锡百度
  • 校园网站的系统建设/百度网盘pc端网页版
  • 番禺门户网站建设/软文模板300字
  • 云浮+网站建设/无锡网站建设seo
  • 微动网站建设/线上营销活动案例
  • 新疆建设局网站首页/有什么推广产品的渠道
  • 衡阳网站建设qiandu1/百度统计怎么使用
  • 统战部门户网站建设情况/培训学校管理制度大全
  • 建设银行六安市分行网站/广州新闻最新消息今天
  • 广州南沙建设网站/uv推广平台
  • 营销型集团网站建设/seo推广哪家服务好
  • 淄博圻谷网站建设制作/2022拉新推广平台
  • 一条龙网站建设哪家好/沈阳seo团队
  • 诸几建设银行网站/佛山seo外包平台
  • 网站建设中应注意的问题/最新做做网站