C++纯虚函数

1.纯虚函数的定义:
在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义。凡是含有纯虚函数的类叫做抽象类。这种类不能声明对象,只是作为基类为派生类服务。除非在派生类中完全实现基类中所有的的纯虚函数,否则,派生类也变成了抽象类,不能实例化对象。
2.引入纯虚函数的原因
1、为了方便使用 多态特性,我们常常需要在基类中定义虚函数。
2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;)。若要使派生类为非抽象类,则编译器要求在派生类中,必须对纯虚函数予以重写以实现多态性。同时含有纯虚函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。
3.相似的概念
多态性
指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种 多态性:编译时 多态性运行时多态性
a.编译时 多态性:通过 重载函数实现
b运行时 多态性:通过虚函数实现。


//
//   纯虚函数
//
///

#include <iostream>
#include <string>
using namespace std ;

// 基类
class Item_Base
{
public:
	// 默认构造函数
	Item_Base( const string& book = "" , double sales_price = 0.0 ) : isbn( book ) , price( sales_price ) { }

	// 拷贝构造函数
	Item_Base( const Item_Base& item ) : isbn( item.isbn ) , price( item.price ) 
	{
	}

	// 重载赋值操作符
	Item_Base& operator= ( const Item_Base& item )
	{
		isbn = item.isbn ;
		price = item.price ;
		return *this ;
	}

	string book() const { return isbn ; }

	virtual double net_price( int n ) const 
	{
		return n * price ;
	}

	virtual ~Item_Base()  {  } 

private:
	string isbn  ;
public:
	double price ;
} ;

// 派生类
class Bulk_Item : public Item_Base
{
public:
	// 构造函数
	Bulk_Item ( const string& book , double sales_price , int qty = 0 , double discount_rate = 0.0 ) 
		: Item_Base( book , sales_price ) , min_qty( qty ) , discount( discount_rate ) { }

	// 默认构造函数
	Bulk_Item() { } 

	// 拷贝构造函数
	Bulk_Item( const Bulk_Item& item ) : Item_Base( item ) , min_qty( item.min_qty ) , discount( item.discount )
	{
	}

	// 重载赋值操作符
	Bulk_Item& operator= ( const Bulk_Item& rhs )
	{
		if( this != &rhs )
		{
			Item_Base::operator =( rhs ) ;
			min_qty = rhs.min_qty ;
			discount = rhs.discount ;
		}
		return *this ;
	}

	double net_price( int n ) const ;
private:
	int min_qty ;
	double discount ;
} ;

double Bulk_Item::net_price( int n ) const
{
	if( n >= min_qty )
	{
		return n * price * ( 1 - discount ) ;
	}
	else
	{
		return n * price ;
	}
}

void print_total( ostream& os , const Item_Base& item , int n )
{
	os << "ISBN: " << item.book() 
	   << "\nnumber_sold: " << n << "\ntotal_price: "
	   << item.net_price( n ) << endl ;
} 

int main()
{
	Item_Base  base( "123456" , 1.2 ) ;
	Bulk_Item  derived( "123456" , 1.2 , 5 , 0.5 ) ;

	print_total( cout , base , 10 ) ;
	cout << endl ;
    print_total( cout , derived , 10 ) ;

	cout << endl ;

	Item_Base temp1 = base ;    // 调用复制构造函数
	Bulk_Item temp2 = derived ; // 调用复制构造函数

	print_total( cout , base , 10 ) ;
	cout << endl ;
    print_total( cout , derived , 10 ) ;

	cout << endl ;


	Item_Base temp_base ;   
	temp_base = base ;     // 复制,调用复制操作符

	Bulk_Item temp_bulk ;
	temp_bulk = derived ;  // 复制,调用复制操作符

	print_total( cout , temp_base , 10 ) ;
	cout << endl ;
    print_total( cout , temp_bulk , 10 ) ;

	return 0 ;
}





<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() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值