没有实现文件(.cpp)的派生类
derived class with no implementation file (.cpp)
在我从同事那里继承的项目中,我有一个带有头和实现的基本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命令以包含补丁,将新的实现文件添加到构建过程中,现在它像一个魅力。
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- Linux的Cpp上的计时器
- 为什么使用 "this" 指针调用派生成员函数?
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- 命名空间中具有.h和.cpp文件的类
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 内置函数可查看CPP中的成员变量
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- Cpp-Tuple使用带有变量的get
- 在派生函数中指定void*参数
- 如何通过派生类函数更改基类中的向量
- 如何委托派生类使用其父构造函数?
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- 有充分的理由在h文件中使用include保护而不是cpp文件吗
- 快速傅立叶变换:使用模板化派生类'undefined reference'即使标头和.cpp文件匹配也会出错
- 从我的driver.cpp调用派生类
- 没有实现文件(.cpp)的派生类
- 在派生类中的CPP文件中定义模板和定义
- *.h文件和*.cpp文件中派生类的定义和声明