C语言中的多态性

合集下载

c八股文面试题

c八股文面试题

c八股文面试题
以下是有关C语言“八股文”面试题的一些示例:
1. 请简述C语言中指针的概念及作用。

2. 描述C语言中内存的分配方式。

3. 什么是C语言的函数?请简要说明函数在程序中的作用。

4. 请解释C语言中的位运算符,并给出相应的应用场景。

5. C语言中结构体是什么?它与联合有何区别?
6. 请简述C语言中内存管理的机制,并举例说明其作用。

7. C语言中的多态性是如何实现的?请举例说明。

8. 什么是C语言的预处理器指令?请举例说明其用法。

9. 请解释C语言中的递归函数,并给出相应的应用场景。

10. C语言中的全局变量和局部变量有什么区别?请举例说明。

以上问题仅供参考,实际面试中,面试官会根据面试者的简历和实际情况进行提问,难度和深度也会有所不同。

建议在面试前做好充分准备,深入理解C语言的基础知识和常用概念,以提高面试通过率。

C语言中的多态

C语言中的多态

C语⾔中的多态⼀、多态的主要特点1、继承体系下。

继承:是⾯向对象最显著的⼀个特性。

继承是从已有的类中派⽣出新的类,新的类能吸收已有类的数据属性和⾏为,并能扩展新的能⼒,已有类被称为⽗类/基类,新增加的类被称作⼦类/派⽣类。

2、⼦类对⽗类的虚函数进⾏重写。

3、虚表。

在⾯向对象语⾔中,接⼝的多种不同现⽅式即为多态。

同⼀操作作⽤于不同的对象,可以有不同的解释,产⽣不同的执⾏结果,这就是多态性。

简单说就是允许基类的指针指向⼦类的对象。

⼆、代码实现1、C++中的继承与多态1 class Base2 {3 public:4 virtual void fun() {} //基类函数声明为虚函数5 int B1;6 };7 class Derived :public Base //Derived类公有继承Base类8 {9 public:10 virtual void fun() { //函数重写,此时基类函数可以声明为虚函数,也可以不声明11 cout << "D1.fun" << endl;12 }13 int D1;14 };15 int main(){16 Base b1; //创建⽗类对象17 Derived d1;//创建⼦类对象1819 Base *p1 = (Base *)&d1;//定义⼀个⽗类指针,并通过⽗类指针访问⼦类成员20 p1->fun();2122 Derived *p2 = dynamic_cast<Derived*> (&b1); //dynamic_cast⽤于将⼀个⽗类对象的指针转换为⼦类对象的指针或引⽤(动态转换)23 p2->fun();2425 getchar();26 return 0;27 }2. C语⾔实现C++的继承与多态1 typedef void(*FUNC)(); //定义⼀个函数指针来实现对成员函数的继承2 struct _Base //⽗类3 {4 FUNC _fun;//由于C语⾔中结构体不能包含函数,故借⽤函数指针在外⾯实现5 int _B1;6 };7 struct _Derived//⼦类8 {9 _Base _b1;//在⼦类中定义⼀个基类的对象即可实现对⽗类的继承10 int _D1;11 };12 void fb_() //⽗类的同名函数13 {14 printf("_b1:_fun()\n");15 }16 void fd_() //⼦类的同名函数17 {18 printf("_d1:_fun()\n");19 }20 int main() {21 _Base _b1;//定义⼀个⽗类对象_b122 _Derived _d1;定义⼀个⼦类对象_d12324 _b1._fun = fb_;//⽗类的对象调⽤⽗类的同名函数25 _d1._b1._fun = fd_;//⼦类的对象调⽤⼦类的同名函数2627 _Base *_p1 = &_b1;//定义⼀个⽗类指针指向⽗类的对象28 _p1-> _fun(); //调⽤⽗类的同名函数2930 _p1 = (_Base *)&_d1;//让⽗类指针指向⼦类的对象,由于类型不匹配所以要进⾏强转31 _p1->_fun(); //调⽤⼦类的同名函数3233 getchar();34 return 0;35 }。

【C++面向对象的程序设计】6多态性

 【C++面向对象的程序设计】6多态性

虚析构函数
析构函数的作用是对象撤销之后清理现场。 在派生类对象撤销时,一般先调用派生类的 析构函数。再调用基类的析构函数。
然而,当定义的是一个指向基类的指针变量, 使用new运算符建立临时对象时,如果基类 中有析构函数,则在使用delete析构时只会 调用基类的析构函数。
这就需要将基类中的析构函数声明为虚函数。
虚函数的声明与使用
声明虚函数的一般格式如下: virtual 函数原型;
⑴ 必须首先在基类中声明虚函数。 ⑵ 派生类中与基类虚函数原型完全相同的成员函 数,即使在说明时前面没有冠以关键字virtual也 自动成为虚函数。
声明虚函数
⑶ 只有非静态成员函数可以声明为虚函数。 ⑷ 不允许在派生类中定义与基类虚函数名字及参数 特征都相同,仅仅返回类型不同的成员函数。 编译时 出错。 ⑸ 系统把函数名相同但参数特征不同的函数视为不 同的函数。 ⑹ 通过声明虚函数来使用C++提供的多态性机制时, 派生类应该从它的基类公有派生。
构函数等内容。
本章内容
静态联编与动态联编 虚函数的声明与使用 纯虚函数和抽象类 虚析构函数
Hale Waihona Puke 静态联编与动态联编所谓联编(tinding),就是使一个计算机程序的不同部 分彼此关联的过程。
静态联编在编译阶段完成,因为所有联编过程都在程 序开始运行之前完成,因此静态联编也叫先前联编或早期 联编。
另一种情况编译程序在编译时并不确切知道应把发送 到对象的消息和实现消息的哪段具体代码联编在一起,而 是在运行时才能把函数调用与函数体联系在一起,则称为 动态联编。
动态联编的实现
C ++语言中的动态联编是通过使用虚函数表 (Virtual Function Table)来实现的,虚函数表也称 为v-表。

C的运行时类型识别实现动态多态性

C的运行时类型识别实现动态多态性

C的运行时类型识别实现动态多态性在C语言中,没有原生的运行时类型识别(Runtime Type Identification,RTTI)机制,而RTTI是实现多态性的关键。

然而,我们可以通过一些技巧和约定来模拟实现动态多态性,即在运行时根据对象的类型来决定调用哪个函数。

本文将介绍一种常用的C语言中实现动态多态性的方法。

一、使用函数指针表进行类型识别为了实现运行时类型识别,我们可以使用函数指针表(Function Pointer Table)来存储不同类型对象的函数指针。

函数指针表是一个包含一组函数指针的数组,数组的索引对应于对象的类型。

首先,我们定义一个基础的类型,作为其他类型的父类型,例如Shape类型:```ctypedef struct {void (*draw)();} Shape;```接下来,我们定义继承自Shape的具体类型,例如Rectangle和Circle:```ctypedef struct {Shape shape;int width;int height;} Rectangle;typedef struct {Shape shape;int radius;} Circle;```我们为每个具体类型实现相应的draw函数:```cvoid rectangle_draw() {printf("Drawing rectangle\n");}void circle_draw() {printf("Drawing circle\n");}```然后,我们为每个具体类型创建函数指针表,并将draw函数指针赋值给相应的表项:```cShape shape;shape.draw = rectangle_draw;Shape shape;shape.draw = circle_draw;```现在,我们可以通过调用shape.draw()来动态地调用相应类型的draw函数。

C语言中的多态实现方式

C语言中的多态实现方式

C语言中的多态实现方式
多态是面向对象编程中一个重要的概念,它允许不同的对象对同一个消息做出不同的响应。

在C语言中,虽然没有内置的多态特性,但我们可以通过一些技巧来实现多态效果。

一种常见的实现多态的方式是使用函数指针。

函数指针可以指向不同的函数,我们可以将函数指针作为参数传递给一个函数,然后根据不同的函数指针调用不同的函数。

这样就可以实现在运行时根据对象类型来选择不同的函数处理。

另一种实现多态的方式是使用结构体和函数指针的组合。

我们可以定义一个结构体,其中包含一个函数指针指向操作函数,然后针对不同类型的对象定义不同的操作函数。

通过这种方式,我们可以在运行时根据对象的类型来调用相应的操作函数,实现多态效果。

除此之外,我们还可以使用函数表来实现多态。

函数表是一个包含函数指针的数组,每个函数指针指向一个操作函数。

我们可以将函数表作为对象的一个成员变量,在运行时根据对象类型选择相应的函数表,然后调用相应的操作函数。

总结来说,虽然C语言本身并不支持多态特性,但通过使用函数指针、结构体和函数表等技巧,我们仍然可以在C语言中实现多态效果。

这些方法需要我们在设计程序结构时仔细思考,合理利用指针和结构体的特性,才能实现灵活而高效的多态效果。

希望以上内容能够帮助您了解C语言中的多态实现方式。

C语言中的多态与继承

C语言中的多态与继承

C语言中的多态与继承多态和继承是面向对象编程中两个重要的概念。

它们不仅在C++等高级语言中有着广泛的应用,而且在C语言中也具备一定的实现方式。

本文将讨论C语言中的多态与继承,探讨它们的概念、特点以及在实际编程中的应用。

一、多态的概念与特点多态是指同一操作作用于不同的对象,可以有不同的解释和实现方式。

在C语言中,要实现多态性通常使用函数指针和结构体来模拟。

通过函数指针,可以实现对不同结构体中相同类型的成员进行访问,进而实现多态。

多态的特点有以下几个方面:1. 同一操作作用于不同对象,可以有不同的表现形式。

2. 多态性可以增加代码的灵活性和可扩展性。

3. 多态性可以提高代码的复用性和可读性。

二、继承的概念与特点继承是面向对象编程中的基本概念之一,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。

在C语言中,要实现继承通常使用结构体嵌套的方式来模拟。

继承的特点有以下几个方面:1. 子类可以拥有父类的属性和方法。

2. 子类可以覆盖父类的方法,实现自己的特定功能。

3. 继承可以实现代码的重用和扩展,提高代码的效率和可维护性。

三、C语言中多态与继承的应用在C语言中,多态和继承可以通过结构体、函数指针以及函数调用的方式来实现。

首先,我们需要定义一个基类结构体,包含一些通用的属性和方法。

然后,针对不同的具体情况,可以定义多个不同的派生类结构体,继承基类的属性和方法,并在派生类中实现自己特定的操作。

接下来,我们需要定义一个函数指针成员,用于指向不同派生类中的方法。

通过函数指针的动态绑定,可以在运行时确定调用哪一个具体的方法,实现多态的效果。

最后,在调用函数的时候,可以使用基类的指针指向不同的派生类对象,通过函数指针调用对应的方法。

由于函数指针的动态绑定,程序会根据对象的实际类型来决定调用哪个方法,实现多态的效果。

通过上述方式,我们可以在C语言中模拟出多态和继承的特性,实现代码的复用、扩展和灵活调用。

c++三大特征的理解

c++三大特征的理解

c++三大特征的理解
C++语言的三大特征是封装、继承和多态。

封装是指将数据和操作数据的方法捆绑在一起,以防止外部访
问和不合法修改,从而保证数据的安全性和一致性。

通过封装,可
以隐藏实现细节,使得对象更容易被使用,并且减少了对外部的依赖。

继承是指一个类可以派生出新的类,新的类可以继承原有类的
属性和方法,并且可以添加新的属性和方法。

继承可以提高代码的
复用性,减少重复编码,同时也能够实现多态性。

多态性是指同一个消息被不同的对象接收时,可以产生不同的
行为。

在C++中,多态性可以通过虚函数和纯虚函数来实现。

多态
性使得程序更加灵活,能够根据不同对象的类型来执行不同的操作,从而提高了代码的可扩展性和可维护性。

总的来说,封装、继承和多态是C++语言的三大特征,它们为
面向对象编程提供了强大的支持,使得程序更加模块化、灵活和易
于扩展。

(C++完整PPT课件) 第 8 章 多态性

(C++完整PPT课件) 第 8 章 多态性

第八章 多态性
4.运算符new和delete重载
//EX8_5.cpp : 演示重载new和delete的程序。其中new通过 //malloc( )函数实现,new的操作数是申请内存单元的字节个数。 //delete通过free( )函数实现,它的操作数是一个指针,即告诉 //系统释放哪里的单元。 #include <iostream.h> #include<malloc.h> class rect { private: int length, width; public: rect ( int l, int w ) { length = l; width = w; }
第八章 多态性
point operator + ( point p1, point p2 ) { return point (p1.x+p2.x, p1.y+p2.y) ; }
point operator - ( point p1, point p2 ) { return point (p1.x- p2.x, p1.y-p2.y) ; } void main( ) { point p1(3, 3), p2(2, 2), p3, p4 ; //声明point类的对象 p3=p1+p2; //两点相加 p4=p1- p2; //两点相减 cout<<"p1+p2: x="<<p3.get_x( )<<", y="<<p3.get_y( )<<endl ; cout<<"p1- p2: x="<<p4.get_x( )<<", y="<<p4.get_y( )<<endl ; } 程序运行结果:p1+p2: x=5, y=5 p1- p2: x=1, y=1
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

point operator++(); 符“++”
point operator--(); 符“--”
//重载前置运算
//重载前置运算
point point::operator++() { if(x<640) ++x; if(y<480) ++y; return *this; } point point::operator--() { if(x>0) --x; if(y>0) --y; return *this; }
数时,如果某个对象使用重载了的成员函数,自身的数据可以直接访问,
就不需要再放在参数表中进行传递,少了的操作数就是该对象本身。
第8章 多态性
8.2.2 运算符重载为成员函数
运算符重载实质上就是函数重载,当运算符重载为成员函数 之后,它就可以自由地访问本类的数据成员了。实际使用时,总 是通过该类的某个对象来访问重载的运算符。如果是双目运算符, 一个操作数是对象本身的数据,由this指针指出,另一个操作数则 需要通过运算符重载函数的参数表来传递;如果是单目运算符, 操作数由对象的this指针给出,就不再需要任何参数。下面分别介 绍这两种情况。 1.双目运算:oprdl B oprd2 对于双目运算符B,如果要重载B为类的成员函数,使之能够 实现表达式oprdl B oprd2(其中oprdl为A类的对象),则应当把B重 载为A类的成员函数,该函数只有一个形参,形参的类型是oprd2 所属的类型。经过重载之后,表达式oprdl B oprd2就相当于函数 调用oprdl.operator B (oprd2)。
8.2.3 运算符重载为友元函数
运算符也可以重载为类的友元函数,这样它就可以自由地访问 该类的任何数据成员。这时,运算所需要的操作数都需要通过函
象时,该实现什么样的功能,这就是运算符重载。运算符重载是 对已有的运算符赋予多重含义,使同一个运算符作用于不同类型 的数据时,导致不同类型的行为。 在运算符重载的实现过程中,首先把指定的运算表达式转化 为对运算符函数的调用,运算对象转化为运算符函数的实参,然 后,根据实参的类型来确定需要调用的函数。这个过程是在编译 过程中完成的。
和动态多态性两种。静态多态性是在编译的过程中确定同名操 作的具体操作对象的,而动态多态性则是在程序运行过程中动
态地确定操作所针对的具体对象的。这种确定操作具体对象的
过程就是联编(binding),也称为绑定。联编是指计算机程序自身 彼此关联的过程。也就是把一个标识符名和一个存储地址联系 在一起的过程。用面向对象的术语讲,就是把一条消息和一个 对象的方法相结合的过程。
//重载运算符“+”和“-”为成员函

};
第8章 多态性
本例中重载的“+”、“-”函数中,都是创建一个临时的无名对象作为返回值:
return point(x+q.x,y+q.y); 这表面上看起来像是对构造函数的调用,但其实并非如此。这是临时对象语法, 它的含义是创建一个临时对象并返回它。当然,也可以按如下形式返回函数值:
第8章 多态性
【例8-2】单目运算符重载为成员函数例题。
#include<iostream.h> class point
{
private: float x,y; public: point(float xx=0,float yy=0){x=xx;y=yy;} float get_x(){return x;} float get_y(){return y;}
第8章 多态性
8.2.1 运算符重载的规则
运算符重载时必须要遵守一定的规则。
①C++中的运算符除了少数几个(类属关系运算符“.”、作用域分 辨 符 “ ::” 、 成 员 指 针 运 算 符 “ * ” 、 sizeof 运 算 符 和 三 目 运 算 符 “?:”)之外,全部可以重载,而且只能重载C++中已有的运算符, 不能臆造新的运算符。 ②重载之后运算符的优先级和结合性都不能改变,也不能改变运算 符的语法结构,即单目运算符只能重载为单目运算符,双目运算符只 能重载为双目运算符。 ③运算符重载后的功能应当与原有功能相类似。 ④重载运算符含义必须清楚,不能有二义性。
第8章 多态性
前置单目运算符和后置单目运算符重载的最主要的区别就在于
重载函数的形参。语法规定,前置单目运算符重载为成员函数时 没有形参,而后置单目运算符重载为成员函数时,需要有一个int
型形参。这个int型参数在函数体中并不使用,纯粹是用来区别前置
与后置,因此,参数表中可以只给出类型名,没有参数名。(例 test_operator.cpp)
{
private:
float x,y; public: point(float xx=0,float yy=0) { x = xx ; y = yy;} float get_x(){return x;} float get_y(){return y;} point operator+(point p1); point operator-(point p1);
};
第8章 多态性
void main()
{ point p1(10,10),p2(200,200); //声明point类的对象
for(int i=0;i<5;i++)
{ cout<<"p1:x="<<p1.get_x()<<",y="<<p1.get_y()<<endl;
++p1;
} for ( i = 0;i<5;i++) { cout<<"p2:x="<<p2.get_x()<<",y="<<p2.get_y()<<endl; --p2; } }
第8章 多态性
2.单目运算
1)前置单目运算:U oprd 对于前置单目运算符U,如“-”(负号)、“++”等,如果要重载U 为类的成员函数,用来实现表达式U oprd(其中oprd为A类的对象), 则U应当重载为A类的成员函数,函数没有形参。经过重载之后, 表达式U oprd相当于函数调用oprd.operator U()。
例如,前置单目运算符“++”重载的语法形式如下:
<函数类型>operator++(); 使用前置单目运算符“++”的语法形式如下:
++<对象>;
第8章 多态性
2) 后置单目运算:opr dV
再来看后置运算符V,如“++”和“--”,如果要将它们重载为 类的成员函数,用来实现表达式oprd++或oprd--(其中oprd为A类的 对象),那么运算符就应当重载为A类的成员函数,这时函数要带 有一个整型(int)形参。重载之后,表达式oprd++和oprd--就相当于 函数调用oprd.operator++(0)和oprd.operator--(0)。 例如,后置单目运算符“++”重载的语法形式如下: <函数类型>operator++(int); 使用后置单目运算符“++”的语法形式如下: <对象>数及类的章节中曾做过详细的讨论,所以在本章中,静
态多态性主要介绍运算符重载;对于动态多态性,将对虚函数作详细介 绍。
第8章 多态性
8.2 运算符重载
C++中预定义的运算符的操作对象只能是基本数据类型。实际上,对于很多用户自 定义的类型(如类),也需要有类似的运算操作。例如点类point。 class point { private: int x , y; public: //构造函数 //显示x值 //显示y值 point ( int xx=0,int yy =0){ x = xx ; y = yy ; } int get_x(); int get_y(); //... };
运算符的重载形式有两种:重载为类的成员函数和重载为类的友 元函数。
第8章 多态性
运算符重载为类的成员函数的一般语法形式如下:
<函数类型> operator <运算符> (形参表) {
函数体;
} 运算符重载为类的友元函数的一般语法形式如下:
friend <函数类型> operator <运算符>(形参表)
第8章 多态性
在C++中,可以通过在运算符函数参数表中是否插入关键字int来 区分前缀和后缀这两种方式。
◆对于前缀方式++ob,可以用运算符函数重载为
ob.operator ++(); 或 operator ++ (X& ob); // 成员函数重载 // 友元函数重载,
其中ob为类X对象的引用
◆ 对于后缀方式ob++,可以用运算符函数重载为 ob.ooperator ++(int); 或 operator++(X& ob,int); // 成员函数重载 // 友元函数重载
在调用后缀方式的函数时,参数int一般被传递给值0。(例 test_operator.cpp)
第8章 多态性 【例8-1】双目运算符重载为成员函数例题。//test_operator.cpp
#include<iostream.h> class point point point::operator+(point q) { return point(x+q.x,y+q.y); } point point::operator-(point q) { return point(x-q.x,y-q.y); } void main() { point p1(3,3),p2(2,2),p3,p4 p3=p1+p2; //两点相加 p4=p1-p2; //两点相减 cout<<p3.get_x()<<“ "<<p3.get_y()<<endl; cout<<p4.get_x()<<“ "<<p4.get_y()<<endl; }
相关文档
最新文档