没有实现文件(.cpp)的派生类

derived class with no implementation file (.cpp)

本文关键字:派生 cpp 实现 文件      更新时间:2023-10-16

在我从同事那里继承的项目中,我有一个带有头和实现的基本c++类。为了便于理解,我将提供示例情况,因为代码本身太大:bthidtransport.h

class BtHidTransport
{
public:
BtHidTransport();    // constructor
protected:
virtual ~BtHidTransport();   // destructor
}    // BtHidTransport

bthidtransport.cpp

BtHidTransport::BtHidTransport
{
}   // constructor
BtHidTransport::~BtHidTransport()
{
}   // destructor

这是基类,现在我们有了派生的类头:
bthidtransportfixes.h:

#include "bthidtransport.h"
class BtHidTransportFixes : public BtHidTransport
{
BtHidTransportFixes(); // constructor
virtual ~BtHidTransportFixes();    // destructor
}   // BtHidTransportFixes

然而,在特定的项目中,BtHidTransportFixes并没有实现(.cpp)文件。项目本身构建时没有出现错误。如果我在运行时用从类实例化新对象

BtHidTransport* createdObject=new BtHidTransportFixes();

并且BtHidTransportFixes没有实现(.cpp)文件,那么就父类而言,执行顺序是什么?我使用Eclipse 4.3.2 for Windows(主机操作系统为Windows 7 64位旗舰版)和ARM DS-5 5.20.2编译器。项目中的任何地方都没有BtHidTransportFixes的实现,我已经在ALL项目文件中搜索了它。编译器优化关闭时,-O0标志显式。以下是构建过程的汇编程序列表:

;;;107        // Create the BT transport first
;;;108        BtHidTransport *btTransport = new BtHidTransportFixes();
00002a  2088              MOVS     r0,#0x88
00002c  f7fffffe          BL       _ZN16StartupAllocatednwEj ; StartupAllocated::operator new(unsigned)
000030  4934              LDR      r1,|L1.260|
000032  2200              MOVS     r2,#0
000034  9100              STR      r1,[sp,#0]
000036  4b34              LDR      r3,|L1.264|
000038  4611              MOV      r1,r2
00003a  f7fffffe          BL       _ZN19BtHidTransportFixesC1EP9BtHidConnP13BtPairingListPK14tBTM_APPL_INFOPK23tBTM_LINK_EVT_CALLBACKS ; BtHidTransportFixes::BtHidTransportFixes()
00003e  4604              MOV      r4,r0

和连接器输出:

Stack Usage for BtHidTransportFixes::BtHidTransportFixes() 0x0 bytes.
Stack Usage for BtHidTransportFixes::BtHidTransportFixes() 0x0 bytes.
Stack Usage for BtHidTransportFixes::BtHidTransportFixes__sub_object() unknown bytes.
BtHidTransportFixes::BtHidTransportFixes() 0x0020587d   Thumb Code     0  20730_ram_ext.symdefs ABSOLUTE
BtHidTransportFixes::BtHidTransportFixes__sub_object() 0x0020587d   Thumb Code     0  20730_ram_ext.symd

构造函数的大小似乎是0,这里执行什么检查?为了简化,我故意删除了构造函数的参数(这里,在StackOverflow对问题的描述中),这是我的错吗?

它不必构建失败。即使虚拟成员函数是在一个定义规则下隐式使用的。

[basic.def.odr](强调矿)

4每个程序应包含每个odr在该程序中使用的非内联函数或变量在废弃声明之外无需诊断。这个定义可以显式显示在程序中,可以在标准或用户定义的库,或者(在适当的时候)隐式定义(请参见[class.cctor]、[class.dtor]和[class.copy])。应在每次翻译中定义内联函数或变量在丢弃语句之外进行odr使用的单元。

您的工具链不必对此发出警告,也不必构建失败。它可以假装一切都很好。在那种情况下,这个程序显然是格式错误的。如果工具链设法解决了这个问题,或者直到运行时崩溃才进行诊断,那么这一切都在合同范围内。

如果一个程序缺少声明的成员函数的实现,那么就根本没有执行——链接器将无法构建可执行文件。

缺失的实现唯一无关紧要的是,是否从未使用过相应的类。在这种情况下,链接器将永远不会被迫寻找实现。

但是,如果你的程序包含——正如你所说的——下面的行

DerivedClass* derivedClass=new DerivedClass();

程序格式不正确(链接器应该抱怨)。

我找到了解决特定问题的方法。生成过程文件(.inc)被指示将头文件bthidtransportfixes.h替换为修补的BThidtransportixes.h,该文件不包含在项目树本身中,但位于Windows用户主目录中,然后将丢失的代码本身从修补的头文件复制到原始文件中。如果我清理项目,操作将反转。真是胡说八道,这个项目一团糟!以下是缺失的构造函数代码,取自补丁:

BtHidTransportFixes::BtHidTransportFixes(BtHidConn            *btHidConn, 
BtPairingList        *hostList, 
const tBTM_APPL_INFO *btmSecCallbacks,
const tBTM_LINK_EVT_CALLBACKS *btmLinkEvtCb) :
BtHidTransport(btHidConn, hostList, btmSecCallbacks, btmLinkEvtCb)
{
#ifdef PROXIMITY_ASSOCIATION_SUPPORT
// Initialize the observer to NULL
proxAssocObserver.pObj = NULL;
#endif
#ifdef FIX_NEED_DISCOVERYLED_TICK
discoveryTickEnabled = hidAppConfig.discoveryLedEnabled;
discoveryTickBasePeriodInMs = 50;
#endif
#ifdef FIX_CQ_911035
ucdConnectRequested = FALSE;
#endif
}

我自己创建了实现文件,将其添加到项目中,将修补的代码放在其中,删除.inc命令以包含补丁,将新的实现文件添加到构建过程中,现在它像一个魅力。