Pure virtual function call error探讨

在实习的单位搞CxImage库时不知为什么在Debug时没有问题,但是Release版里竟然跳出个Pure virtual function call error! 啥东西呀,竟然遇上了,就探个究竟吧!

MSDN上的解释

http://forums.msdn.microsoft.com/zh-CN/clr/thread/bfa759a8-0cc0-4d65-8711-d2d0d6765687/

 

这时讲得很详细

http://www.artima.com/cppsource/pure_virtual.html

 

看看Codeproject上的一个例子

http://www.codeproject.com/KB/cpp/PureVirtualFunctionCall.aspx

 

(1)出现 Pure virtual function call 的原因是:

the child destructor is called and finished, so, we don’t have an object of type child now, but the current object (which is only being destructed) is of type Parent, so all calls in the destructor are calls to functions in this object. So, you can get a pure virtual function.

继承类的对象析构被调用,而且完成了释放,那么现在这个对象就不存在了,但是当前的对象(正在释构的父类对象)却要调用其子类的虚函数实现(因为自身是纯虚函数),所以就会出现Pure virtual function call error!

 

(2) 由面向对象的概念知,对象的析构是子类先析构再到父类析构,所以如果在父类中要调用自身的虚纯数将会很危险了,而且在是运行时出现的。

 

以下是codeproject的例子

 

Class Parent

{

public: Parent() { } 

~Parent() {  

ClearALL();  

}  

void ClearALL() 

{  

ThePure();   //调用自身的纯虚函数,包装一下是因为直接调用编译器会识别出这样调用是有问题的!

} 

 virtual bool ThePure() = 0 ;

}; 

class Child : public Parent

{

public: Child() { }  

~Child() { }  //The implementation of the pure virtual function  virtual bool ThePure()  

{  

return true; 

} 

};   

void main()

{

 Child c;

}

C析构时,虚函数表里的 ThePure()  已经注销,那么父类 Parent 里的ClearALL() 里的ThePure() 虚表指针就会指向一个空地址(成了 dangling pointer ), 所以在Parent里调用 ClearALL() 就会出错了

 

(3)如果上面的情况还算直观的话,看看下面的一种造成 pure virtual function call的情况就更隐蔽了。

//不过我在VC6里没有问题



class Base 

{

public:

    virtual void function() = 0;

};



class B : public Base



{

public:

    virtual void function() 

    {

        cout<<"pure function call in B"<<endl;



    }

};



class A 

{

public:

    A(B* b):_b(b) {}

    ~A() 

    {

        _b->function();

    }

    B* _b;

};



B b;

a(&b);



int main()

{

    return 0;

}

 

 

这种情况在某些编译器下会出pure virtual function call错误。主要的原因是因为全局变量的释放顺序不确定,全局变量A依赖全局变量B。如果编译器决定让B先释放,A后释放。那么,当A析构时,_b是一个dangling pointer。此时如果b对象的内存系统没有释放的话,那么bvptr表指向的是Basevptr,而不是B的。此时,_b->function()就指向pure virtual function了。详细情况可以到看看
     
http://www.cnblogs.com/whjiang/archive/2007/10/22/932880.html
   
(5)论坛上关于出现pure virtual function call 的情况总结:
   
     
   

1. 基类构造器直接调用虚函数

2. 基类析构器直接调用虚函数

3. 基类构造器间接调用虚函数

4. 基类析构器间接调用虚函数

5. Calling a virtual function via a dangling pointer.

(4)为了在遇到 pure virtual function call 时不致于程序蹦掉,可以实现在一基类的纯虚函数,但要记住找出原因后要删掉实现的代码
   
   

   
     
   
<think> 首先,用户的问题是基于UVM(Universal Verification Methodology)的,它是在SystemVerilog中使用的验证方法学。用户问的是UVM中virtual functionpure virtual function的区别。 从系统指令中,我需要: - 所有行内数学表达式使用$...$格式(但这个问题可能不涉及数学表达式)。 - 独立公式使用$$...$$并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识。 用户提供了站内引用: - 引用[1]: 解释了抽象类和纯虚方法。虚拟类不能被直接实例化,只能被扩展;纯虚方法没有实体。 - 引用[2]: 讨论了多态性和虚方法。实方法看句柄类型,虚方法看对象类型;建议将方法定义为virtual以利用多态性。 用户的当前问题是:"我想了解UVM中virtual functionpure virtual function的区别"。我需要参考上一次的用户问题和我的回答,但在这个对话中,这是第一次交互,所以没有上一次的问题和回答。用户说:"上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。" 但在上下文里,没有显示上一次的问题和回答。所以我只能基于当前信息。 关键点:UVM是基于SystemVerilog的,SystemVerilog支持面向对象编程,包括虚函数和纯虚函数。 在SystemVerilog中: - **virtual function**: 允许方法被派生类覆盖(override),支持多态。这意味着当函数被声明为virtual时,实际调用的函数版本取决于对象的实际类型,而不是引用类型。 - **pure virtual function**: 是在抽象类中声明的函数,没有实现(body)。任何包含纯虚函数的类都是抽象类,不能被直接实例化。派生类必须提供纯虚函数的实现。 在UVM中,这些概念被广泛使用,特别是在定义基类(如uvm_object、uvm_component)等时。 结构我的回答: 1. **清晰介绍概念**:简单定义virtual functionpure virtual function在SystemVerilog/UVM中的含义。 2. **解释区别**: - virtual function可以有默认实现,可以被覆盖。 - pure virtual function没有实现,必须在派生类中实现。 - 包含纯虚函数的类是抽象类,不能被实例化。 3. **UVM具体例子**:UVM中常见的场景,比如在uvm_component或uvm_transaction中定义虚函数。 4. **添加引用标识**:因为我需要参考提供的引用,我需要自然地添加引用标识。例如,在解释时提到抽象类和纯虚方法时,引用[^1];提到多态性时,引用[^2]。 5. **生成相关问题**:在回答结束后,添加"相关问题"部分。 使用中文回答。 生成相关问题: - 类似示例中的格式:"§§相关问题§§",然后列出问题。 - 问题应围绕主题,例如: 1. 在UVM中如何实现多态性? 2. 纯虚函数在UVM测试平台中有哪些应用? 3. 为什么UVM推荐使用虚函数? 添加引用标识的例子: - 在句子末尾添加[^1]或[^2],如:"纯虚方法只能在抽象类中定义[^1]。" - 确保引用标识自然地融入文本。 完整回答结构: - 开头直接回答问题。 - 详细解释区别。 - 提供UVM上下文。 - 结束相关问题。 </think> ### UVM中virtual functionpure virtual function的区别 在UVM(Universal Verification Methodology,基于SystemVerilog)中,virtual function(虚函数)和pure virtual function(纯虚函数)是面向对象编程的核心概念,用于实现多态性和抽象类机制。它们的本质区别在于函数的实现要求和类实例化的限制。以下我将基于SystemVerilog规范逐步解释它们的差异,并结合UVM的实际应用场景进行分析。 #### 1. **基本定义和作用** - **virtual function**: - 这是一个可以被子类覆盖(override)的函数,但它在基类中有一个默认的实现体。 - 在UVM中,常用于定义基类方法(如`uvm_component`或`uvm_object`中的函数),允许派生类根据需要重新定义函数行为,而不改变基类的接口。 - 由于虚函数支持多态性,调用时实际执行的函数版本取决于对象的实际类型(而非引用句柄的类型),这在UVM的动态组件配置中非常有用[^2]。 - 示例:在UVM测试序列中,虚函数可用于通用的`start`方法,子类可以覆盖它来自定义行为。 - **pure virtual function**: - 这是一个没有实现体的函数声明(只有原型),必须使用`pure virtual`关键字定义。 - 包含纯虚函数的类称为抽象类(virtual class),不能被直接实例化;只有派生类提供了所有纯虚函数的实体后,派生类才能被实例化[^1]。 - 在UVM中,纯虚函数常用于定义接口规范或基类契约(如`uvm_reg_adapter`中的方法),强制派生类实现特定逻辑,确保设计的完整性。 - 示例:在UVM寄存器模型中,基类可能定义一个纯虚函数`bus2reg`,要求所有适配器子类必须实现它来处理总线转换。 #### 2. **关键区别** 下表总结了virtual functionpure virtual function的主要区别: | 特征 | virtual function | pure virtual function | |------|------------------|------------------------| | **实现要求** | 在基类中有默认实现体(可选的),子类可以选择覆盖它。 | 在基类中无实现体(只有声明),子类必须强制覆盖并提供实现。 | | **类实例化限制** | 基类可以被实例化(除非有其他限制),不影响派生类的实例化。 | 基类是抽象类,不能被直接实例化;派生类只有在实现所有纯虚函数后才能实例化[^1]。 | | **语法区别** | 声明时使用`virtual function`,后跟函数体和实现代码。 | 声明时使用`pure virtual function`,无函数体(以分号结束)。 | | **UVM应用场景** | 用于提供可扩展的默认行为,例如`uvm_component::build_phase`的默认实现,子类可选择性覆盖。 | 用于定义接口契约,例如`uvm_driver`中的`run_phase`纯虚函数,强制每个驱动子类实现具体逻辑。 | | **多态性支持** | 支持多态:调用时基于对象实际类型执行(而非句柄类型),但基类的默认实现可作为回退[^2]。 | 支持多态:同样基于对象类型执行,但由于无默认实现,强制派生类定义行为,避免未定义错误。 | 在UVM中,这种区别直接影响验证组件的设计: - virtual function提供灵活性,允许重用基类代码(如日志记录或配置设置),减少冗余。 - pure virtual function强制标准化接口(如事务处理或回调机制),确保UVM框架的一致性。例如,在UVM工厂模式中,基类定义纯虚函数以确保所有子类实现必要的方法。 #### 3. **UVM中的实际示例** 考虑一个简单的UVM测试场景,定义一个基类`base_test`: ```systemverilog virtual class base_test extends uvm_test; // 纯虚函数:无实现,强制子类覆盖 pure virtual function void configure_env(); // 虚函数:有默认实现,子类可选择覆盖 virtual function void report_phase(uvm_phase phase); uvm_report_info("Test", "Default report message"); endfunction endclass class my_test extends base_test; // 必须实现纯虚函数 function void configure_env(); // 具体配置代码 endfunction // 可选覆盖虚函数 virtual function void report_phase(uvm_phase phase); // 自定义报告行为 endfunction endclass ``` - 在上例中,`configure_env`是pure virtual function,如果`my_test`未实现它,编译会报错,且`base_test`不能被实例化。 - `report_phase`是virtual function,提供了默认日志输出,子类可覆盖以添加特定信息。这体现了UVM的多态性:当调用`report_phase`时,实际执行取决于对象类型(如my_test实例),而非句柄类型[^2]。 #### 4. **为什么在UVM中推荐使用虚函数?** - UVM强烈建议将方法定义为virtual(包括普通虚函数),以充分利用多态性。这允许传入不同子类对象时调用不同方法,提高代码复用和扩展性[^2]。例如,在UVM序列或回调中,虚函数支持动态行为切换。 - pure virtual function则用于强制接口完整,避免未实现错误,这在构建可重用验证IP(VIP)时至关重要[^1]。 总之,virtual functionpure virtual function在UVM中的核心区别在于实现强制性和类抽象层次:前者提供可覆盖的默认行为,后者定义必须实现的接口契约。合理使用它们可以增强UVM测试平台的可维护性和灵活性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值