search
HomeBackend DevelopmentC#.Net TutorialStatic polymorphism is related to dynamic polymorphism and virtual functions

What is polymorphism

It literally means multiple forms. The word polymorphism originally originated from Greek, and its meaning is "multiple forms", which means a situation with multiple forms or shapes. In the C++ language, polymorphism has a broader meaning. meaning. In the C++ primer book, multiple types with inheritance relationships are called polymorphic types, because we can use "various forms" of these types without caring about their differences. Baidu Encyclopedia mentions that in object-oriented languages, the many different implementations of interfaces are polymorphic. QuoteCharlie Calverts' description of polymorphism - Polymorphism is a technique that allows you to set a parent object to be equal to one or more of its child objects. After assignment, the parent object can be based on the current assignment Properties given to its sub-objects behave differently. To put it simply, it is one sentence: it is allowed to assign a pointer of a subclass type to a pointer of a parent class type. Polymorphism is implemented in Object Pascal and C++ through virtual functions.
It is impossible to understand it deeply and clearly only from the conceptual description. Let’s analyze it in detail below.

1. Object type

The object type mentioned here can be reflected by the following diagram: Let’s illustrate it through code examples


 1 class Derived1:public Base 2 {}; 3 class Derived2:public Base 4 {}: 5 int main() 6 { 7      Derived1* p1 = new Derived1; 8      Base = p1; 9      Derived2* p2 = new Derived1;10      Base = p2;11      return = p212 }

The static type is always known at compile time. It is the type of the variable when it is declared or the type generated by the expression ;Dynamic type is the type of object in memory represented by a variable or expression. Dynamic types are not known until run time.

2. Static polymorphism and dynamic polymorphism

The difference between static polymorphism and dynamic polymorphism can be reflected in the following figure:

Static polymorphism State

Static polymorphism is also called static binding or early binding. The compiler completes it during compilation. The compiler can infer which function is to be called based on the type of the function argument (may perform implicit type conversion). If there is a corresponding function, it will call the function. Otherwise a compilation error will occur.


 1 int Add(int left,int right) 2 { 3      return left + right; 4 } 5 float Add(float left, float right) 6 { 7      return left + right; 8 } 9 int main()10 {   
11     cout<p>Here I classify <a href="http://www.php.cn/wiki/197.html" target="_blank">overloading</a> as static polymorphism. The implementation of overloading is: the compiler modifies the names of functions with the same name based on different parameter lists of the functions, and then these functions with the same name become different functions (at least for the compiler). The function call has been determined between compilers and is static (remember: it is static). In other words, their addresses are bound at compile time (early binding). It is precisely because of this nature of overloading that some people conclude that overloading is just a language feature and has nothing to do with polymorphism or object-oriented. Based on object-oriented programming, the concept of overloading does not belong to "object-oriented programming". But polymorphism is a relatively broad concept. In order to facilitate understanding, we will not analyze their differences in depth here. We will talk about it after the detailed analysis of other <a href="http://www.php.cn/wiki/44.html" target="_blank"> parts of polymorphism is completed. </a><a href="http://www.php.cn/java/java-alibaba-qita.html" target="_blank">Dynamic polymorphism</a></p>Dynamic binding: During program execution (not during compilation), determine the actual type of the referenced object, and call the corresponding method according to its actual type. When using the virtual keyword to modify a member function of a class, it indicates that the function is a virtual function, and the derived class needs to be reimplemented, and the compiler will implement dynamic binding. <h4></h4><p></p><pre class="brush:php;toolbar:false">              FunTest1(         cout FunTest1(     pBase->FunTest2(     pBase->FunTest3(     pBase->FunTest4(        }


When we use a base class pointer or reference to call a function defined in the base class, we do not know what type the real object of the function is. , because it may be an object of a base class or an object of a derived class. If the function is a virtual function, it will not know which version is executed until runtime. The judgment is based on the real type of the object to which the reference or pointer is bound.

Destructor

, static type function, friend function, inline function and virtual function

        CTest&  =( CTest&       *     fri end voi d FunTestFri end() ;
12 }

什么是虚函数

其实在前面的虚拟继承中我们已经用到了虚函数这个概念,在那里我们是为了解决菱形普通继承中访问二义性的问题,但在多态中,他有更大的作用。百度百科中对虚函数是这么说的:在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数,用法格式为:virtual 函数返回类型 函数名(参数表) {函数体};实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。形象的解释为“求同存异”,它的作用就是实现多态性。

简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。


 1 class A 2 { 3     public: 4         virtual void print(){coutprint();18     p2->print();19     return 0;20 }

毫无疑问,class A的成员函数print()已经成了虚函数,那么class B的print()成了虚函数了吗?回答是Yes,我们只需在把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数。所以,class B的print()也成了虚函数。那么对于在派生类的相应函数前是否需要用virtual关键字修饰,那就是你自己的问题了(语法上可加可不加,不加的话编译器会自动加上,但为了阅读方便和规范性,建议加上)。

运行代码,输出的结果是This is A和This is B。

总结:指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。

析构函数与虚函数

当在析构函数前面加virtual关键字时报错:,我们来分析一下原因。

1、虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初 始化,将无法进行。

2、构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。

虚函数的意思就是开启动态绑定,程序会根据对象的动态类型来选择要调用的方法。然而在构造函数运行的时候,这个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定。(动态绑定是根据对象的动态类型而不是函数名,在调用构造函数之前,这个对象根本就不存在,它怎么动态绑定?)
编译器在调用基类的构造函数的时候并不知道你要构造的是一个基类的对象还是一个派生类的对象。

静态类型函数与虚函数

当我们在静态类型函数前加virtual关键字时报错:分析:

1、 static成员不属于任何类对象或类实例,所以即使给此函数加上virutal也是没有任何意义的。

2、static函数没有this指针,并且不会进入虚函数表的。当通过指针或者引用调用时根本无法把this指针传递给static函数,从而无法体现出多态。静态成员函数与普通成员函数的差别就在于缺少this指针,没有这个this指针自然也就无从知道name是哪一个对象的成员了。

友元函数与虚函数

当我们在友元函数前加virtual关键字时报错:

 因为C++不支持友元函数的继承,对于没有继承特性的函数没有虚函数的说法。

内联成员函数与虚函数

内联函数就是为了在代码中直接展开,减少函数调用花费的代价,虚函数是为了在继承后对象能够准确的执行自己的动作,这是不可能统一的。(再说了,inline函数在编译时被展开,虚函数在运行时才能动态的邦定函数)

赋值运算符的重载与虚函数

当我们把赋值运算符的重载定义为虚函数时编译可以通过,但是一般不建议这么做虽然可以将operator=定义为虚函数, 但使用时容易混淆。

1、无法给派生类的自有成员赋值;

2、调用虚函数要进行查虚表等一系列操作,效率下降。

析构函数与虚函数

析构函数设为虚函数的作用:在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。


 1 #include <stdafx.h> 2 #include <stdio.h> 3 class A 4 { 5     public: 6     A(); 7     virtual~A(); 8 }; 9     A::A()10     {}11     A::~A()12     {13     printf("Delete class APn");14     }15 class B : public A16 {17     public:18     B();19     ~B();20 };21     B::B()22     { }23     B::~B()24     {25     printf("Delete class BPn");26     }27 int main(int argc, char* argv[])28 {29     A *b=new B;30     delete b;31     return 0;32 }</stdio.h></stdafx.h>

输出结果为:Delete class B     Delete class A
如果把A的virtual去掉:那就变成了Delete class A也就是说不会删除派生类里的剩余部分内容,也即不调用派生类的虚函数

析构函数总结:

1. 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了。
2. 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚特性来自父类。
3. 有虚函数的类,几乎可以确定要有个虚析构函数。
4. 如果一个类不可能是基类就不要申明析构函数为虚函数,虚函数是要耗费空间的。
5. 析构函数的异常退出会导致析构不完全,从而有内存泄露。最好是提供一个管理类,在管理类中提供一个方法来析构,调用者再根据这个方法的结果决定下一步的操作。
6. 在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。
7.在析构函数中也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。
8. 记得在写派生类的拷贝函数时,调用基类的拷贝函数拷贝基类的部分。

总结:

1、 派生类重写基类的虚函数实现多态, 要求函数名 、 参数列表、 返回值完全相同。 (协变除外)。

2、 基类中定义了 虚函数, 在派生类中该函数始终保持虚函数的特性。

3、 只 有类的非静态成员 函数才能定义为虚函数, 静态成员 函数不能定义为虚函数。

4、 如果在类外定义虚函数, 只 能在声明函数时加virtual关键字, 定义时不用加。

5、 构造函数不能定义为虚函数, 虽然可以将operator=定义为虚函数, 但最好不要这么做, 使用时容易混淆。

6、 不要在构造函数和析构函数中调用虚函数, 在构造函数和析构函数中, 对象是不完整的, 可能会出现未定义的行为。

 7、 最好将基类的析构函数声明为虚函数。 ( 因为派生类的析构函数跟基类的析构函数名称不一样, 但是构成覆盖, 这里编译器做了特殊处理)

8、 虚表是所有类对象实例共用的。

The above is the detailed content of Static polymorphism is related to dynamic polymorphism and virtual functions. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
MySQL中如何实现数据的多态存储和多维查询?MySQL中如何实现数据的多态存储和多维查询?Jul 31, 2023 pm 09:12 PM

MySQL中如何实现数据的多态存储和多维查询?在实际应用开发中,数据的多态存储和多维查询是一个非常常见的需求。MySQL作为常用的关系型数据库管理系统,提供了多种实现多态存储和多维查询的方式。本文将介绍使用MySQL实现数据的多态存储和多维查询的方法,并提供相应的代码示例,帮助读者快速了解和使用。一、多态存储多态存储是指将不同类型的数据存储在同一个字段中的技

深入解析C语言中static关键字的作用和用法深入解析C语言中static关键字的作用和用法Feb 20, 2024 pm 04:30 PM

深入解析C语言中static关键字的作用和用法在C语言中,static是一种非常重要的关键字,它可以被用于函数、变量和数据类型的定义上。使用static关键字可以改变对象的链接属性、作用域和生命周期,下面就来详细地解析一下static关键字在C语言中的作用和用法。static变量和函数:在函数内部使用static关键字定义的变量称为静态变量,它具有全局生命周

如何在PHP中使用多态和继承来处理数据类型如何在PHP中使用多态和继承来处理数据类型Jul 15, 2023 pm 07:41 PM

如何在PHP中使用多态和继承来处理数据类型引言:在PHP中,多态和继承是两个重要的面向对象编程(OOP)概念。通过使用多态和继承,我们可以更加灵活地处理不同的数据类型。本文将介绍如何在PHP中使用多态和继承来处理数据类型,并通过代码示例展示它们的实际应用。一、继承的基本概念继承是面向对象编程中的一种重要概念,它允许我们创建一个类,该类可以继承父类的属性和方法

PHP中私有静态方法的作用及应用场景PHP中私有静态方法的作用及应用场景Mar 23, 2024 am 10:18 AM

PHP中私有静态方法的作用及应用场景在PHP编程中,私有静态方法是一种特殊的方法类型,它只能在定义它的类内部访问,外部无法直接调用。私有静态方法通常用于类的内部逻辑实现,提供了一种封装和隐藏细节的方式,同时又具有静态方法的特性,可以在不实例化类对象的情况下被调用。下面将探讨私有静态方法的作用及应用场景,并提供具体的代码示例。作用:封装和隐藏实现细节:私有静态

继承、多态与接口:PHP面向对象的三大特性继承、多态与接口:PHP面向对象的三大特性May 11, 2023 pm 03:45 PM

PHP是一种服务器端编程语言,自PHP5之后开始支持面向对象编程(OOP)。OOP的核心思想是将数据和行为封装在对象中,以提高程序的可维护性和可扩展性。在PHP中,面向对象编程具有三大特性:继承、多态与接口。一、继承继承是指一个类可以从另一个类中继承属性和方法。被继承的类称为父类或基类,继承的类称为子类或派生类。子类可以通过继承获得父类中的属性和方法,并且可

快速掌握静态相对定位的技巧与方法快速掌握静态相对定位的技巧与方法Jan 18, 2024 am 11:18 AM

快速静态相对定位是网页开发中非常重要的一种定位方式。它可以使元素相对于其正常位置进行微调的同时,仍然保持在文档流中的位置。在本文中,我将详细介绍快速静态相对定位的使用方法,以及一些常见的应用场景。首先,我们需要了解快速静态相对定位的基本概念。在CSS中,元素的定位方式有四种:静态定位、相对定位、绝对定位和固定定位。静态定位是默认的定位方式,元素的位置通过文档

PHP中的多态与派发机制的关系PHP中的多态与派发机制的关系Jul 07, 2023 pm 05:45 PM

PHP中的多态与派发机制的关系在面向对象编程中,多态是一种强大的概念,它允许不同的对象对同一消息做出不同的响应。PHP作为一门强大的开发语言,也支持多态性,并且与之紧密相关的是派发机制。本文将通过代码示例来探讨PHP中的多态与派发机制的关系。首先,我们来了解一下什么是多态。多态是指对象能够根据自己的实际类型来调用相应的方法。通过使用多态,程序可以根据具体对象

Go 语言中的多态和重载怎样实现?Go 语言中的多态和重载怎样实现?Jun 10, 2023 am 10:25 AM

Go语言作为一门静态类型语言,看似不能像动态语言那样实现多态和重载。但是,Go语言利用接口的特性实现了多态,而重载的实现则更加简单和精准。实现多态的方法Go语言中的接口可以在调用过程中实现多态,接口可以描述一个对象的行为,任何实现了接口所有方法的类型都可以称之为该接口类型的实例。通过这种方式,只需定义好接口类型,实现不同的具体类型,就可以实现多态。下面是一个

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software