精华内容
下载资源
问答
  • C++基础:什么是C++的多态性

    千次阅读 2020-12-28 18:50:10
    多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。多态(polymorphisn),字面意思多种形状。 C++多态性是通过虚函数来实现的,虚函数允许子类重新定义...

    多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。多态(polymorphisn),字面意思多种形状。

    C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。(这里我觉得要补充,重写的话可以有两种,直接重写成员函数和重写虚函数,只有重写了虚函数的才能算作是体现了C++多态性)而重载则是允许有多个同名的函数,而这些函数的参数列表不同,允许参数个数不同,参数类型不同,或者两者都不同。编译器会根据这些函数的不同列表,将同名的函数的名称做修饰,从而生成一些不同名称的预处理函数,来实现同名函数调用时的重载问题。但这并没有体现多态性。

    多态与非多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并生产代码,是静态的,就是说地址是早绑定的。而如果函数调用的地址不能在编译器期间确定,需要在运行时才确定,这就属于晚绑定。

    那么多态的作用是什么呢,封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。

    最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。如果没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了。

    一、定义

    纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”

    virtual void funtion()=0

    二、引入原因

    1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。

    2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。

    为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()=0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。

    三、相似概念

    1、多态性

    指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性,运行时多态性。

    a、编译时多态性:通过重载函数实现

    b、运行时多态性:通过虚函数实现。

    2、虚函数

    虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态覆盖(Override)

    3、抽象类

    包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。

    虚析构函数的特点(动态绑定)

    Base*p=new Derived();

    delete p;

    删除Base类型的指针时,会调用析构函数,如果Base类型的析构函数的虚函数,则会按照虚函数的动态绑定,先调用Derived的析构函数,然后调用Base的析构函数。

    以这样的方式会调用多次析构函数。

    C++类成员和数据成员初始化总结

    C++为类中提供类成员的初始化列表

    类对象的构造顺序是这样的:

    1.分配内存,调用构造函数时,隐式/显示的初始化各数据成员

    2.进入构造函数后在构造函数中执行一般计算

    1.类里面的任何成员变量在定义时是不能初始化的。

    2.一般的数据成员可以在构造函数中初始化。

    3.const数据成员必须在构造函数的初始化列表中初始化。

    4.static要在类的定义外面初始化。

    5.数组成员是不能在初始化列表里初始化的。

    6.不能给数组指定明显的初始化。

    这6条一起,说明了一个问题:C++里面是不能定义常量数组的!

    C++类的初始化:

    1.初始化列表:CSomeClass::CSomeClass() : x(0), y(1){}

    2.类外初始化:int CSomeClass::myVar=3;

    3.const常量定义必须初始化,C++类里面使用初始化列表;

    4.C++类不能定义常量数组。

    免费领取C++学习资料一份

    在这里插入图片描述

    展开全文
  • 多态性(c++)

    2018-05-23 12:48:29
    多态性是指一段程序能够处理多种类型对象的能力。在C++中,多态性可以通过强制多态、重载多态、类型参数化多态、包含多态等形式来实现。强制多态是通过将一种类型的数据转换成另一种类型的数据来实现的,也就是数据...

    多态性是指一段程序能够处理多种类型对象的能力。在C++中,多态性可以通过强制多态、重载多态、类型参数化多态、包含多态等形式来实现。

    强制多态是通过将一种类型的数据转换成另一种类型的数据来实现的,也就是数据类型转换。重载是指给同一个名字的赋予不同的含义(函数重载和运算符重载)。这两种多态属于特殊多态性,只是表面的多态性。

    包含多态和类型参数化多态属于一般多态性,是真正的多态性。C++中采用虚函数实现包含多态。模板是C++实现参数化多态性的工具,分为函数模板和类模板两种。

    展开全文
  • 多态性是面向对象编程的又一个重要特征,它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为,这使得同一个属性或方法在父类及其各个子类中具有不同的含义。 对面向对象来说...

    多态性是面向对象编程的又一个重要特征,它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为,这使得同一个属性或方法在父类及其各个子类中具有不同的含义。

    对面向对象来说,多态分为编译时多态和运行时多态。其中编译时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的方法。通过编译之后会变成两个不同的方法,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是大家通常所说的多态性。

    Java 实现多态有 3 个必要条件:继承、重写和向上转型。只有满足这 3 个条件,开发人员才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而执行不同的行为。

    • 继承:在多态中必须存在有继承关系的子类和父类。
    • 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
    • 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法。

    例 1
    下面通过一个例子来演示重写如何实现多态性。例子使用了类的继承和运行时多态机制,具体步骤如下。

    1)创建 Figure 类,在该类中首先定义存储二维对象的尺寸,然后定义有两个参数的构造方法,最后添加 area() 方法,该方法计算对象的面积。代码如下:

    public class Figure {
        double dim1;
        double dim2;
        Figure(double d1, double d2) {
            // 有参的构造方法
            this.dim1 = d1;
            this.dim2 = d2;
        }
        double area() {
            // 用于计算对象的面积
            System.out.println("父类中计算对象面积的方法,没有实际意义,需要在子类中重写。");
            return 0;
        }
    }
    

    2)创建继承自 Figure 类的 Rectangle 子类,该类调用父类的构造方法,并且重写父类中的 area() 方法。代码如下:

    public class Rectangle extends Figure {
        Rectangle(double d1, double d2) {
            super(d1, d2);
        }
        double area() {
            System.out.println("长方形的面积:");
            return super.dim1 * super.dim2;
        }
    }
    

    3)创建继承自 Figure 类的 Triangle 子类,该类与 Rectangle 相似。代码如下:

    public class Triangle extends Figure {
        Triangle(double d1, double d2) {
            super(d1, d2);
        }
        double area() {
            System.out.println("三角形的面积:");
            return super.dim1 * super.dim2 / 2;
        }
    }
    

    4)创建 Test 测试类,在该类的 main() 方法中首先声明 Figure 类的变量 figure,然后分别为 figure 变量指定不同的对象,并调用这些对象的 area() 方法。代码如下:

    public class Test {
        public static void main(String[] args) {
            Figure figure; // 声明Figure类的变量
            figure = new Rectangle(9, 9);
            System.out.println(figure.area());
            System.out.println("===============================");
            figure = new Triangle(6, 8);
            System.out.println(figure.area());
            System.out.println("===============================");
            figure = new Figure(10, 10);
            System.out.println(figure.area());
        }
    }
    

    从上述代码可以发现,无论 figure 变量的对象是 Rectangle 还是 Triangle,它们都是 Figure 类的子类,因此可以向上转型为该类,从而实现多态。

    5)执行上述代码,输出结果如下:

    长方形的面积:
    81.0
    ===============================
    三角形的面积:
    24.0
    ===============================
    父类中计算对象面积的方法,没有实际意义,需要在子类中重写。
    0.0
    
    展开全文
  • C++ 实验七 多态性与虚函数

    千次阅读 多人点赞 2018-05-11 10:37:11
    cout圆柱体的体积为:"注: 已经出现过的error: 存在的问题: 注意cmath头文件 可行优化: 使用构造函数对类对象进行初始化,同时注意纯虚函数的构造函数使用时的问题 欢迎访问陈风的个人博客

    问题背景:
    将任意一个平面图形(如长方形、三角形、圆形等)沿其法线方向平移一定长度,它所扫过的空间区域为一个柱体。例如,长方形、圆形和三角形所形成的柱体分别如图(a)(b)©所示。
    实验题:
    柱体的体积 和表面积 计算公式分别为:

    式中, 和 分别为柱体的底面积和底面周长。
    请用C++语言编写面向对象程序,实现柱体体积和表面积的计算(圆柱和四棱柱为必做内容,三棱柱为选做内容)。例如底面半径为2、高为4的圆柱,体积为50.27,表面积为75.40;以长为3、宽为2的长方形为底面,高为5的四棱柱,体积为30,表面积为62。
    提示:
    注意:以下定义的类中,若未给出构造函数、析构函数及输出函数,请根据需要添加。
    1、 定义一个描述平面图形的抽象类Plane,其成员函数如下表:

    函数名 访问权限 形参 返回值 功能 虚函数?
    area public void float 求面积 纯虚函数
    girth public void float 求周长 纯虚函数

    2、定义一个描述柱体的类Body:

    (1) 类Body的成员变量如下表:

    变量名 访问权限 类型 含义
    pbasic private Plane * 指向柱体的底面图形
    high private float 给出柱体的高

    (2) 类Body的成员函数如下表:

    函数名 访问权限 形参 返回值 功能 虚函数?
    volume public void float 求体积 否
    surfaceArea public void float 求表面积 否
    3、从抽象类Plane派生出具体类(如长方形类Rectangle、圆形类Circle和三角形类triangle),根据实际情况,覆盖基类Plane的纯虚函数area和girth,如下表。

    函数名 访问权限 形参 返回值 功能 虚函数?
    area public void float 求面积 自动为虚函数
    girth public void float 求周长 自动为虚函数

    (1) 长方形类Rectangle的成员变量为

    变量名 访问权限 类型 含义
    a private float 给出长方形的长
    b private float 给出长方形的宽

    (2) 圆形类Circle的成员变量为

    变量名 访问权限 类型 含义
    a private float 给圆形的半径

    (3) 三角形类Triangle的成员变量为

    变量名 访问权限 类型 含义
    A private Point 给出三角形的顶点A
    B private Point 给出三角形的顶点B
    C private Point 给出三角形的顶点C

    其中,Point为描述平面点的类,其成员变量为:

    变量名 访问权限 类型 含义
    x public float 给出顶点的x坐标
    y public float 给出顶点的y坐标

    附代码
    !!!编译环境 DevC++ 5.11 TDM-GCC 4.9.2 64-Bit Release
    头文件 iquery.h

    #ifndef  _IQUERY_H
    #define _IQUERY_H 1
    	using namespace std;
    	class Plane
    	{
    		public:
    			virtual float area() const =0;
    			virtual float girth() const =0;
    	}
    	class Body
    	{
    		public:
    			float volume();
    			float surfaceArea();
    			void setpb(Plane *p);
    			void sethigh();
    		private:
    			Plane *pbasic;
    			float high;
    	};
    	
    	class Point
    	{
    		public:
    			void setpoint();
    			float x;
    			float y;
    	};
    	class Rectangle: public Plane
    	{
    		public:
    			void setrec();
    			virtual float area()const;
    			virtual float girth()const;
    		private:
    			float a;
    			float b;
    	};
    	class Circle: public Plane
    	{
    		public:
    			void setcir();
    			virtual float area()const;
    			virtual float girth()const;
    		private:
    			float a;
    	};
    	class Triangle: public Plane
    	{
    		public:
    			void settri();
    			virtual float area()const;
    			virtual float girth()const;
    		private:
    			Point A;
    			Point B;
    			Point C;
    	};
    #endif
    

    头文件实现文件 iquery,cpp

    #include <iostream>
    #include "string"
    #include "iquery.h"
    #include "iomanip"
    #include "cmath" 
    using namespace std; 
    float Body::volume(){
    	return pbasic->area()*high;
    }
    float Body::surfaceArea(){
    	return 2*pbasic->area()+pbasic->girth()*high;
    }
    void Body::setpb(Plane *p){
    	pbasic=p;
    }
    void Body::sethigh(){
    	cin >>high;
    }
    void Rectangle :: setrec(){
    	cout << "输入四棱柱底面的长:" ;
    	cin >>a; cout<<endl;
    	cout << "输入四棱柱底面的宽:" ;
    	cin >> b; cout <<endl;
    }
    float Rectangle :: area()const{
    	return a*b;
    }
    float Rectangle ::girth()const{
    	return 2*(a+b);
    }
    void Circle :: setcir(){
    	cout <<"输入圆柱的半径:" ;
    	cin >> a;cout<<endl;
    }
    float Circle :: area()const{
    	return 3.14159*a*a;
    }
    float Circle :: girth()const{
    	return 2*3.14159*a;
    }
    void Point ::setpoint(){
    	cin >> x >>y;
    }
    void Triangle :: settri(){
    	cout << "输入三棱柱底面顶点A的<x y>坐标:" ;
    	A.setpoint();cout<<endl;
    	cout << "输入三棱柱底面顶点B的<x y>坐标:" ;
    	B.setpoint();cout<<endl;
    	cout << "输入三棱柱底面顶点C的<x y>坐标:" ;
    	C.setpoint();cout<<endl;
    }
    float Triangle :: area()const{
    	float m;
    	m=A.x*B.y+A.y*C.x+B.x*C.y-A.x*C.y-A.y*B.x-B.y*C.x;
    	if(m>0) return m/2;
    	else return -m/2;
    }
    float Triangle :: girth()const{
    	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y))+sqrt((C.x-B.x)*(C.x-B.x)+(C.y-B.y)*(C.y-B.y))+sqrt((A.x-C.x)*(A.x-C.x)+(A.y-C.y)*(A.y-C.y));
    }
    
    

    源码 main.cpp

    #include <iostream>
    #include "string"
    #include "iquery.h"
    #include "iomanip"
    #include "cmath" 
    
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    using namespace std;
    int main(int argc, char** argv) {
    	Body body;
    	Circle c;
    	Rectangle r;
    	Triangle t;
    	body.setpb(&c);
    	c.setcir();
    	cout << "输入圆柱体的高:";
    	body.sethigh();
    	cout<<"圆柱体的体积为:"<<body.volume()<<endl;
    	cout<<"圆柱体的表面积为:"<<body.surfaceArea()<<endl;
    	cout<<endl;
    	body.setpb(&r);
    	r.setrec();
    	cout <<"输入四棱柱的高:";
    	body.sethigh();
    	cout<<"四棱柱的体积为:"<<body.volume()<<endl;
    	cout<<"四棱柱的表面积为:"<<body.surfaceArea()<<endl;
    	cout<<endl;
    	body.setpb(&t);
    	t.settri();
    	cout << "输入三棱柱的高:";
    	body.sethigh();
    	cout<<"三棱柱的体积为:"<<body.volume()<<endl;
    	cout<<"三棱柱的表面积为:"<<body.surfaceArea()<<endl; 
    	return 0; 
    }
    

    注:
    已经出现过的error:

    存在的问题:

    1. 注意cmath头文件

    可行性优化:

    1. 使用构造函数对类对象进行初始化,同时注意纯虚函数的构造函数使用时的问题

    欢迎访问陈风的个人博客

    展开全文
  • 多态性是面向对象编程的又一个重要特征,它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为,这使得同一个属性或方法在父类及其各个子类中具有不同的含义。 对面向对象来说...
  • 1多态性概述 多态性含义 在C++中多态表现为同一形式的函数调用, 可能调用不同的函数实现 多态性的表现形式 参数多态函数模板和类模板 包含多态继承了虚函数的派生类同名函数 重载多态函数重载和运算符重载 强制...
  • Java面向对象的三个特性(封装性、继承性、多态性) 首先我们再来提一下面向对象: 面向对象是一种符合人类思维习惯的编程思想,显示生活中存在各种形态不同的事物,这些事物之间存在着各种各样的联系(每种事物都...
  • 虚函数与多态性12.1 多态性的概念12.2 虚函数的定义12.3 抽象类12.4 实例研究12.1 多态性(polymorphism)的概念多态性是OOP的重要特征之一多态一词最初来源于希腊语Polumorphos含义是具有多种形式或形态的情形多态性...
  • 一、多态性的概念 多态性(polymorphism)是面向对象程序设计的一个重要特征。如果一种语言只支持类而不支持多态,是不能被称为面向对象语言的,只能说是基于对象的,如Ada、VB。C++支持多态性,利用多态性可以设计和...
  • 类的多态性的概念

    千次阅读 2013-08-27 16:32:10
    多态性(polymorphism)是面向对象程序设计的一个重要特征。利用多态性可以设计和实现一个易于扩展的系统。 在C++程序设计中,多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容...
  • 多态性-运算符重载

    千次阅读 2016-07-21 22:56:50
    运算符重载是指对已有的运算符赋予多重含义。 必要: C++中预定义的运算符其运算对象只能是基本数据类型,而不适合用户自定义的类型(如类类型)。 实现机制: 将指定的运算表达式转化为对运算符函数的调用,...
  • 面向对象的特点,封装性,继承性,多态性

    万次阅读 多人点赞 2015-01-29 19:37:02
    4.多态性,简单来说就是一个程序中同名的多个不同方法共存的情况,通常使用方法的重载和重写(也叫覆盖)来实现类的多态性多态性允许以统一的风格编写程序,以处理种类繁多的已存在的类以及相关类,多态的实现并不...
  • 目:应用多态设计学生类 生成表示学生的类XS,提供成员函数dispXM()、dispXB()和dispNL...再生成类GZS表示高中生和类DXS表示大学生,同样包含相同含义的数据成员xm、xb和nl,也包括成员函数dispXM()、dispXB()和dispNL()。
  • 程序将确定该对象每次执行所需的含义或用法,从而减少了重复代码。 我国有句俗语:“龙生九子,各有不同”。这就是多态。多态是同一类事物具有的多种形态。多态是面向对象编程的重要特点之一。 Python本身就是一种...
  • 多态性与虚函数

    千次阅读 2016-07-24 15:49:55
    多态就是一个事物有多重状态,在C++程序设计中,多态性是指具有不同功能的函数可以用一个函数名,这样就可以用同一个函数名实现不同的功能。  从系统的角度看,多态分为静态多态和动态多态。静态多态是利用重载...
  • 实验6 多态性与虚函数(P285)

    千次阅读 2018-05-15 15:16:33
    pb的函数调用如果有virtual则根据多态性调用派生类的,如果没有virtual则是正常的静态函数调用,还是调用基类的,所以有virtual的f函数调用输出Derived::,其它两个没有virtual则还是输出Base::。 3 . 分析并调试...
  • 面向对象程序设计语言C++中的多态性 C++是以C语言为基础,支持数据抽象和面向对象的程序设计语言。C++对C语言的扩充部分汲取了许多著名语言中最优秀的特征,如从Algo168中吸取了操作符重载机制等。由于C++语言具有...
  • C++ 多态性的实现方式

    千次阅读 2013-11-04 18:03:29
    C + + 中多态性的实现方式  多态性是面向对象程序设计的一大支柱,它指的是在基类中定义的属性或服务被派生类继承之后,可以表现出不同的行为. 也就是指一段程序能够处理不同类型对象的能力. 在面向对象程序...
  • C++静态多态性之函数重载

    千次阅读 2016-04-23 22:45:01
    C++静态多态性 C++静态多态性包括函数重载与缺省参数,运算符重载,宏多态,类的早起绑定。注意C语言没有重载机制。 函数重载要深入理解函数重载需要了解下列几个问题: - 什么是函数重载 - 为什么需要函数重载...
  • 多态性

    2013-04-07 14:13:57
    面向对象的多态性可以分为四类:重载多态、强制多态、包含多态和参数多态。运算符重载属于强制多态。运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为。运算符重载的...
  • C++的封装性、继承性和多态性概念

    千次阅读 2012-08-08 17:19:58
    封装 (encapsulation) 封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码...封装的目的是增强安全和简化编程,使用者不必了解具体的实现细节,而只是要通过 外
  • 面向对象程序设计具有4个共同特征:抽象性、封装性、继承性和多态性
  • 【C++研发面试笔记】2. 多态性

    千次阅读 2016-10-01 22:27:38
    多态性2.1 多态性来源多态性指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。 最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的...
  • C++支持两种多态性:编译时多态性,运行时多态性。    a、编译时多态性:通过重载函数实现   b、运行时多态性:通过虚函数实现。   2、虚函数   虚函数是在基类中被声明为virtual,并在派生类中...
  • C语言的多态性,你的多态你做主

    千次阅读 2011-02-26 10:42:00
    然而在人们的直观感觉中,多态的含义大约等同于“同一个方法对于不同类型的输入参数均能做出正确的处理过程,并给出人们所期望获得的结果”,也许这正体现了人们对于多态性所能达到的效果所寄予的期望:使程序能够...
  • c++类的多态性教程

    2011-02-11 15:21:20
    运算符重载是对已有的运算符赋予多重含义 必要 C++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类) 实现机制 将指定的运算表达式转化为对运算符函数的调用,运算对象转化为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 42,932
精华内容 17,172
关键字:

多态性的含义