没有实现文件 (.cpp) 的派生 class
derived class with no implementation file (.cpp)
在我从同事那里继承的项目中,我有基础 c++ class 和 header 和实现。为了便于理解,我将提供示例情况,因为代码本身太大:
bthidtransport.h:
class BtHidTransport
{
public:
BtHidTransport(); // constructor
protected:
virtual ~BtHidTransport(); // destructor
} // BtHidTransport
bthidtransport.cpp:
BtHidTransport::BtHidTransport
{
} // constructor
BtHidTransport::~BtHidTransport()
{
} // destructor
这是基础class,现在我们得到class header:
bthidtransportfixes.h:
#include "bthidtransport.h"
class BtHidTransportFixes : public BtHidTransport
{
BtHidTransportFixes(); // constructor
virtual ~BtHidTransportFixes(); // destructor
} // BtHidTransportFixes
但是,在特定项目中,BtHidTransportFixes 没有实现 (.cpp) 文件。项目本身构建没有错误。如果我在运行时从 class 实例化新的 object 并使用:
BtHidTransport* createdObject=new BtHidTransportFixes();
和BtHidTransportFixes没有实现(.cpp)文件,parent的执行顺序是什么class?我正在为 Windows 使用 Eclipse 4.3.2(主机 OS 是 Windows 7 64bit Ultimate)使用 ARM DS-5 5.20.2 编译器。项目中的任何地方都没有 BtHidTransportFixes
的实现,我在 所有项目文件 中搜索过它。使用 -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
constructor的大小好像是0,这里到底执行了什么?为了简化,我特意删除了构造函数的参数(此处,在 Whosebug 问题描述中),这是我的错吗?
如果程序缺少已声明成员函数的实现,则根本不会执行 - 链接器将无法构建可执行文件。
唯一没有实现的缺失无关紧要的是,如果从未使用过相应的 class。在这种情况下,链接器永远不会被迫寻找实现。
但是如果你的程序包含——正如你所说的——下面一行
DerivedClass* derivedClass=new DerivedClass();
程序格式错误(链接器应该抱怨)。
它不必构建失败。即使在一个定义规则下隐式使用虚拟成员函数。
[basic.def.odr] (emphasis mine)
4 Every program shall contain exactly one definition of every
non-inline function or variable that is odr-used in that program
outside of a discarded statement; no diagnostic required. The
definition can appear explicitly in the program, it can be found in
the standard or a user-defined library, or (when appropriate) it is
implicitly defined (see [class.ctor], [class.dtor] and [class.copy]).
An inline function or variable shall be defined in every translation
unit in which it is odr-used outside of a discarded statement.
您的工具链不必对此发出警告或无法构建。它可以假装一切都很好。在那种情况下,程序显然是病式的。如果工具链设法绕过问题,或者直到发生运行时崩溃才对其进行诊断,这一切都在合同范围内。
我找到了特定问题的解决方案。指示生成过程文件 (.inc) 将 header 文件 bthidtransportfixes.h 替换为已修补的 bthidtransportfixes.h,它不包含在项目树本身中,但驻留在 Windows 用户主目录 中,然后从修补程序中复制丢失的代码本身header 为原创。如果我清理项目,则操作相反。胡说八道,这个项目一团糟!这里缺少构造函数代码,取自补丁:
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 命令以包含补丁,将新的实现文件添加到构建过程和它现在就像一个魅力。
在我从同事那里继承的项目中,我有基础 c++ class 和 header 和实现。为了便于理解,我将提供示例情况,因为代码本身太大: bthidtransport.h:
class BtHidTransport
{
public:
BtHidTransport(); // constructor
protected:
virtual ~BtHidTransport(); // destructor
} // BtHidTransport
bthidtransport.cpp:
BtHidTransport::BtHidTransport
{
} // constructor
BtHidTransport::~BtHidTransport()
{
} // destructor
这是基础class,现在我们得到class header:
bthidtransportfixes.h:
#include "bthidtransport.h"
class BtHidTransportFixes : public BtHidTransport
{
BtHidTransportFixes(); // constructor
virtual ~BtHidTransportFixes(); // destructor
} // BtHidTransportFixes
但是,在特定项目中,BtHidTransportFixes 没有实现 (.cpp) 文件。项目本身构建没有错误。如果我在运行时从 class 实例化新的 object 并使用:
BtHidTransport* createdObject=new BtHidTransportFixes();
和BtHidTransportFixes没有实现(.cpp)文件,parent的执行顺序是什么class?我正在为 Windows 使用 Eclipse 4.3.2(主机 OS 是 Windows 7 64bit Ultimate)使用 ARM DS-5 5.20.2 编译器。项目中的任何地方都没有 BtHidTransportFixes
的实现,我在 所有项目文件 中搜索过它。使用 -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
constructor的大小好像是0,这里到底执行了什么?为了简化,我特意删除了构造函数的参数(此处,在 Whosebug 问题描述中),这是我的错吗?
如果程序缺少已声明成员函数的实现,则根本不会执行 - 链接器将无法构建可执行文件。
唯一没有实现的缺失无关紧要的是,如果从未使用过相应的 class。在这种情况下,链接器永远不会被迫寻找实现。
但是如果你的程序包含——正如你所说的——下面一行
DerivedClass* derivedClass=new DerivedClass();
程序格式错误(链接器应该抱怨)。
它不必构建失败。即使在一个定义规则下隐式使用虚拟成员函数。
[basic.def.odr] (emphasis mine)
4 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see [class.ctor], [class.dtor] and [class.copy]). An inline function or variable shall be defined in every translation unit in which it is odr-used outside of a discarded statement.
您的工具链不必对此发出警告或无法构建。它可以假装一切都很好。在那种情况下,程序显然是病式的。如果工具链设法绕过问题,或者直到发生运行时崩溃才对其进行诊断,这一切都在合同范围内。
我找到了特定问题的解决方案。指示生成过程文件 (.inc) 将 header 文件 bthidtransportfixes.h 替换为已修补的 bthidtransportfixes.h,它不包含在项目树本身中,但驻留在 Windows 用户主目录 中,然后从修补程序中复制丢失的代码本身header 为原创。如果我清理项目,则操作相反。胡说八道,这个项目一团糟!这里缺少构造函数代码,取自补丁:
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 命令以包含补丁,将新的实现文件添加到构建过程和它现在就像一个魅力。