C++ 纯虚函数 和 函数参数

本文介绍了纯虚函数的概念及用途,包括其语法格式、在基类与派生类中的应用,以及如何通过纯虚函数定义抽象类。此外,还讨论了函数参数的相关特性,如参数的求值顺序、默认值设定及数组作为参数的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

纯虚函数

 

纯虚函数是在声明虚函数时被“初始化”为0的函数:
        一般形式:virtual 函数类型 函数名(参数列表)=0;

纯虚函数与抽象类

    在定义一个表达抽象概念的基类时,有时可能会无法给出某些成员函数的具体实现。这时,就可以将这些函数声明为纯虚函数。

    纯需函数的声明格式如下:

    virtual 类型 函数名(参数表)=0;

    声明了纯虚函数的基类只是用于继承,仅作为一个接口,具体功能在其派生类中实现。
    声明了纯虚函数的类,称为抽象类。抽象类只能用作基类来派生新类,而不能用来创建对象。

 

纯虚函数没有函数体;最后的“ =0” 并不代表函数返回值为 0 ,它只起形式上的作用,告诉编译器“这是纯虚函数”;这个一个声明语句,最后有分号。

声明纯虚函数是告诉编译器,“在这里声明了一个虚函数,留待派生类中定义”。在派生类中对此函数提供了定义后,它才能具备函数的功能,可以被调用。

纯虚函数的作用是在基类中为其派生类保留了一个函数的名字,以便派生类根据需要对它进行定义。如果在一个类中声明了纯虚函数,而在其派生类中没有对该函数定义,则该函数在派生类中仍为纯虚函数。

 

 

 

 

 

函数参数

 

函数参数的求值顺序  

当一个函数带有多个参数时,C++语言没有规定在函数调用时实参的求值顺序。而编译
器根据对代码进行优化的需要自行规定对实参的求值顺序。有的编译器规定自左至右,
有的编译器规定自右至左,这种对求值顺序的不同规定,对一般参数来讲没有影响。但
是,如果实参表达式中带有副作用的运算符时,就有可能产生由于求值顺序不同而造成
了二义性。例如:int z = add_int(++x, x+y);,这样,在不同的编译器就有可能生产
不同的结果。 

设置参数的默认值 

在C++语言中,允许在函数的说明或定义时给一个或多个参数指定默认值。但是,要求在
一个指定了默认值的参数的右边,不能出现没有指定默认值的参数。例如: 

int add_int(int x, int 10); 

在上述对函数add_int()的说明中,对该函数的最右边的一个参数指定了默认值。 

在函数调用时,编译器按从左至右的顺序将实参与形参结合,当实参的数目不足时,编译
器将按同样的顺序用说明中或定义中的默认值来补足所缺少的实参。例如,如有下列的函
数调用表达式: 

add_int(15) 

它将与下列调用表达式: 

add_int(15, 10) 

是等价的。 

在给某个参数指定默认值是,不仅可以是一个数值,而且还可以是任意复杂的表达式。 

使用数组作函数参数 

数组作函数参数可以分为如下三种情况:(这三种情况的结果相同,只是所采用的调用
机制不同) 

1. 形参和实参都用数组 

调用函数的实参用数组名,被调用函数的形参用数组,这种调用的机制是形参和实参共
用内存中的同一个数组。因此,在被调用函数中改变了数组中某个无素的值,对调用函
数该数组的该元素值也被改变,因为它们是共用同一个数组。 

2. 形参和实参都用对应数组的指针 

在C++中,数组名被规定为是一个指针,该指针便是指向该数组的首元素的指针,国为
它的值是该数组首元素的地址值,因此,数组名是一个常量指针。 

实际中,形参和实参一个用指针,另一个用数组也是可以的。在使用指针时可以用数组
名,也可以用另外定义的指向数组的指针。 

3. 实参用数组名形参用引用 

如何对数组类型使用引用方式,这里先做如下说明:先用类型定义语句定义一个int型的
数组类型,如下所示: 

typedef int array[8]; 

然后,使用array来定义数组和引用。 

示例: 

#include <iostream.h> 
typedef int array[8]; 
int a[8] = {1, 3, 5, 7, 9, 11, 13}; 
void fun(array &b, int n) 
{ 
for(int i=0; i<n-1; i++) 
b[7]+=b[i]; 
} 

void main() 
{ 
int m=8; 
fun(a, m); 
cout<<a[7]<<endl; 
} 
 


该程序中,在fun()函数中,使用了引用作形参,调用时所对应的实参应该是一个数组
名,这里的引用是给数组起个别名。在fun()函数中对数组b的操作,就相当于b所引用
数组a的操作。在C++中,常用这种调用方式。

<think>好的,我现在需要详细介绍一下C++中的纯虚函数虚函数。首先,我得回忆一下这两个概念的基本定义区别。 虚函数(Virtual Function)是在基类中使用virtual关键字声明的成员函数,允许在派生类中被重写(override)。当通过基类指针或引用调用虚函数时,实际调用的是对象的动态类型对应的函数版本,这就是多态性的体现。例如,基类Animal有一个虚函数speak(),派生类DogCat分别重写这个函数,那么通过Animal指针调用speak()会根据实际对象类型执行不同的实现。 然后,纯虚函数(Pure Virtual Function)是在基类中声明但没有实现的虚函数,通过语法`virtual 返回类型 函数名(参数列表) = 0;`来定义。包含纯虚函数的类称为抽象类(Abstract Class),不能实例化,只能作为接口供派生类继承。派生类必须实现所有的纯虚函数,否则它们也会成为抽象类。例如,基类Shape有一个纯虚函数draw(),派生类CircleRectangle必须实现draw()才能被实例化。 接下来,我需要比较两者的区别。虚函数可以有默认实现,而纯虚函数没有,必须由派生类实现。含有纯虚函数的类是抽象类,不能创建对象,而含有虚函数的类仍然可以实例化,除非虚函数被声明为纯虚函数。 还要考虑使用场景。虚函数用于实现运行时多态,允许基类提供默认行为,派生类可以选择是否覆盖。纯虚函数则用于定义接口,强制派生类实现特定方法,确保所有子类都有该功能。 可能需要注意的细节包括:构造函数不能是虚函数,而析构函数通常应该是虚函数,尤其是在有继承关系的情况下,以确保正确释放资源。此外,C++11引入了overridefinal关键字,增强了对虚函数重写的安全性控制。 需要验证一下纯虚函数是否有例外情况。比如,纯虚函数在基类中可以有定义吗?虽然语法上可以提供一个实现,但派生类仍然必须重写它,调用时需要明确指定基类作用域。这可能在某些设计模式中有用,但比较少见。 最后,总结两者的作用重要性,强调它们在实现多态接口设计中的关键角色。可能需要给出简单的代码示例,比如基类定义虚函数纯虚函数,派生类继承并实现它们,展示多态的行为。</think>以下是C++虚函数与纯虚函数的对比详解: 一、核心概念 1. 虚函数(Virtual Function) - 声明方式:基类中用 virtual 关键字修饰 - 特性:允许派生类重写(override)成员函数 - 调用机制:运行时根据对象实际类型动态绑定(动态多态) - 可实例化性:包含虚函数的类可以实例化 2. 纯虚函数(Pure Virtual Function) - 声明方式:在虚函数声明后加 = 0 - 特性:强制派生类必须实现的接口规范 - 类特性:使所在类成为抽象类(不能实例化) - 语法示例:virtual void draw() = 0; 二、核心差异对比表 | 特性 | 虚函数 | 纯虚函数 | |---------------------|-----------------------|--------------------------| | 实现要求 | 基类可提供默认实现 | 基类无实现,必须由派生类实现 | | 类实例化能力 | 允许实例化 | 使类变为抽象类,禁止实例化 | | 派生类强制实现要求 | 可选择性重写 | 必须实现所有纯虚函数 | | 典型用途 | 提供可扩展的默认行为 | 定义接口规范 | 三、使用场景分析 1. 虚函数典型应用场景: ```cpp class Animal { public: virtual void speak() { // 可被子类覆盖的默认实现 std::cout << "Animal sound" << std::endl; } }; class Dog : public Animal { public: void speak() override { // 选择性覆盖基类实现 std::cout << "Woof!" << std::endl; } }; ``` 2. 纯虚函数典型应用场景: ```cpp class Shape { // 抽象基类 public: virtual void draw() = 0; // 强制接口规范 }; class Circle : public Shape { public: void draw() override { // 必须实现的接口 std::cout << "Drawing circle" << std::endl; } }; ``` 四、关键注意事项 1. 虚析构函数原则:当类存在虚函数时,应声明虚析构函数 ```cpp class Base { public: virtual ~Base() = default; // 虚析构函数确保正确释放资源 }; ``` 2. 现代C++特性(C++11+): - 使用override显式标记重写(提高代码安全性) ```cpp class Derived : public Base { public: void func() override; // 明确表示重写基类虚函数 }; ``` 3. 特殊用法:纯虚函数可提供实现(需通过基类限定符调用) ```cpp class Interface { public: virtual void api() = 0; }; // 纯虚函数的实现(不常见但合法) void Interface::api() { std::cout << "Default implementation" << std::endl; } class Impl : public Interface { public: void api() override { Interface::api(); // 显式调用基类实现 // 添加具体实现... } }; ``` 五、设计模式中的应用 1. 虚函数:模板方法模式(基类定义算法框架,子类重写具体步骤) 2. 纯虚函数:策略模式(定义统一接口,具体策略强制实现) 理解这两个概念的区别与应用场景,是掌握C++面向对象设计多态编程的关键基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值