C++ 纯虚函数

虚函数 

在基类中将一个函数声明为虚函数,使该函数具有虚属性,那么其所有派生函数中该函数的重写都具备了虚属性,也就使得基类指针可以调用派生类实例中继承自该基类的所有成员函数,且若有重写,调用的都是重写后的函数。

纯虚函数

声明纯虚函数可使当前类变成抽象类,禁止该类被实例化,并要求其非抽象类的派生类必须实现该函数。

下面展示虚函数和纯虚函数的代码示例,注意观察注释内容:

class Base
{
public:
	virtual void print() = 0;//纯虚函数,可以有函数体,可实例化的派生类必须重写它
	virtual void play() {//虚函数,有函数体,若派生类没有重写它,就原样继承下来
		cout << "Base play!" << endl;
	}
	virtual ~Base() = 0;//纯虚析构函数,必须要有函数体
	//virtual ~Base(){}	//很多情况下,基类的虚函数都会有函数体,将析构函数声明为纯虚函数是一种抽象化基类、不许其实例化的一种方法。
};
void Base::print() {
    //被声明为纯虚函数,仍可以有函数体
    //但派生类若想实例化,必须重写纯虚函数,派生类中可以调用基类有函数体的纯虚函数(Base::print())
	cout << "Base print!" << endl;
}
Base::~Base(){
    //被声明为纯虚析构函数,根据C++类的规则,因为其派生类析构函数会调用基类的析构函数,所以必须有函数体,否则不知道你执行了啥
}

1、纯虚函数对类最大的束缚就是:类中一旦出现纯虚函数,就不可实例化了;

2、纯虚函数还是可以有函数体,只不过最终还是要被派生类重写,在派生类的函数中可以调用基类中有函数体的纯虚函数;

3、为使派生类能完全释放资源,基类析构函数必须声明为虚函数,否则,在用基类指针new一个派生类对象后,delete该指针就只能回收与基类相关的资源,造成内存泄漏;

4、纯虚析构函数必须要有函数体,根据C++析构函数的调用规则,派生类会调用基类析构函数,如果基类析构函数没有函数体会造成函数调用失败而报错,这是纯虚析构函数与普通纯虚函数不同之处。

<think>好的,我现在要详细回答用户关于C++纯虚函数的问题。用户想了解纯虚函数的概念、用法和实现细节。首先,我需要回顾一下自己之前学过的相关知识,确保准确无误。 首先,纯虚函数的定义。根据引用[5],纯虚函数在基类中声明但没有定义,格式是在函数声明后加上“=0”。例如:virtual void func() = 0; 这告诉编译器这个函数在派生类中必须被实现,否则派生类也会成为抽象类,无法实例化。这一点需要明确说明。 然后,纯虚函数的作用。引用[2]提到,纯虚函数的主要目的是实现多态和规范接口。抽象基类通过纯虚函数约束派生类必须实现特定的方法,这样在运行时可以通过基类指针调用派生类的具体实现。比如Line类中的area()和volume()函数,如果声明为纯虚函数,派生类必须实现它们,否则无法实例化对象。这也符合引用[5]中提到的,纯虚函数作为接口规范,确保派生类遵守约定。 接下来,纯虚函数的用法。需要说明如何声明纯虚函数,以及如何在派生类中覆盖它们。例如,基类中声明纯虚函数后,派生类必须提供具体实现。引用[4]提到,如果父类中的纯虚函数带有参数,忘记在派生类中实现会导致编译错误,这可以用来强制子类实现特定方法。同时,引用[3]指出,抽象类除了纯虚函数,还可以包含其他成员函数和变量,但只有虚函数才能被声明为纯虚函数,普通成员函数和顶层函数不行。例如,代码示例中的错误情况需要避免。 还要注意,抽象类不能实例化,只能作为接口使用。引用[2]中的例子说明,即使指针类型是基类,也能调用派生类的方法,这就是多态的体现。此外,引用[3]提到,一个类只要有至少一个纯虚函数就是抽象类,但可以有其他非纯虚函数,这增加了灵活性。 实现细节方面,可能需要讨论纯虚函数的析构函数。通常,基类的析构函数应该是虚的,以确保正确释放资源。但如果是纯虚析构函数,是否需要提供实现?根据C++标准,纯虚析构函数必须有定义,因为派生类析构时会调用基类的析构函数,否则会导致链接错误。这一点可能需要在回答中提到。 另外,用户可能想知道纯虚函数与普通虚函数的区别。普通虚函数在基类中可以有默认实现,而纯虚函数没有,但引用[4]中的例子显示纯虚函数实际上可以有函数体,但这并不常见,可能用于提供默认实现,同时强制派生类重写。不过通常认为纯虚函数没有实现,需要派生类必须覆盖。 可能还需要举一些代码示例,比如基类Animal中的纯虚函数speak(),派生类Dog和Cat必须实现它。这样可以直观展示纯虚函数的用法和多态的效果。同时,结合引用中的例子,如Line类和其派生类的情况,说明多态的应用。 最后,要确保回答结构清晰,分点说明概念、作用、用法、实现细节等,并生成相关问题,帮助用户进一步学习。需要检查引用是否正确应用,比如引用[2]关于多态的例子,引用[5]关于接口规范的部分。 总结一下,回答应该涵盖: 1. 纯虚函数的定义和语法 2. 纯虚函数的作用(接口规范、多态) 3. 如何使用纯虚函数(声明、派生类实现) 4. 注意事项(抽象类不可实例化、纯虚析构函数的处理) 5. 示例代码 6. 常见问题或误区(如纯虚函数能否有函数体) 同时,生成的相关问题应该引导用户深入理解,比如设计模式中的应用、与接口的关系、性能影响等。</think>### C++纯虚函数使用及实现详解 #### 一、核心概念 **纯虚函数**是C++中实现多态和接口规范的核心机制,通过在基类中声明 `virtual 返回类型 函数名(参数) = 0` 的形式定义。例如: ```cpp class Shape { public: virtual double area() const = 0; // 纯虚函数 }; ``` 此时 `Shape` 成为**抽象类**,无法直接实例化[^5]。 #### 二、核心作用 1. **接口规范**:强制派生类必须实现特定功能(如引用[5]中“规范继承类的程序员必须实现这个函数”) 2. **多态支持**:通过基类指针/引用调用派生类实现(如引用[2]中Line类的多态示例) 3. **代码扩展性**:分离接口与实现,降低模块耦合度 #### 三、使用规范 1. **声明语法**: ```cpp virtual 返回类型 函数名(参数列表) = 0; ``` 2. **派生类必须实现**: ```cpp class Circle : public Shape { public: double area() const override { // 必须实现 return 3.14 * radius * radius; } }; ``` 3. **抽象类特性**: - 包含至少一个纯虚函数 - 可以包含普通成员函数和成员变量(引用[3]) - 不可直接实例化,但可定义指针/引用 #### 四、实现细节 1. **纯虚函数与普通虚函数对比**: | 特性 | 纯虚函数 | 普通虚函数 | |------------|-------------------|------------------| | 函数体 | 无(但可选择性实现[^4]) | 必须有 | | 类性质 | 使类成为抽象类 | 不影响类实例化 | | 派生类要求 | 必须覆盖 | 可选覆盖 | 2. **特殊场景处理**: - **纯虚析构函数**:必须提供实现 ```cpp class Base { public: virtual ~Base() = 0; }; Base::~Base() {} // 必须实现 ``` - **带参数的纯虚函数**: ```cpp virtual void log(const std::string& message) = 0; ``` #### 五、典型应用场景 1. **接口定义**(如引用[2]的图形类示例): ```cpp class DatabaseInterface { public: virtual bool connect(const std::string& uri) = 0; virtual void disconnect() = 0; }; ``` 2. **策略模式**: ```cpp class SortStrategy { public: virtual void sort(vector<int>& data) = 0; }; ``` #### 六、常见误区 1. **错误1**:试图实例化抽象类 ```cpp Shape s; // 编译错误:cannot declare variable of abstract type ``` 2. **错误2**:未覆盖纯虚函数 ```cpp class Square : public Shape {}; // 编译错误:未实现area() ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值