c++ - derived class with no implementation file (.cpp)
问题描述
In project I've inherited from coworker, I have base c++ class with header and implementation. For the sake of understanding, I will provide example situation, because the code itself is too big: bthidtransport.h:
class BtHidTransport
{
public:
BtHidTransport(); // constructor
protected:
virtual ~BtHidTransport(); // destructor
} // BtHidTransport
bthidtransport.cpp:
BtHidTransport::BtHidTransport
{
} // constructor
BtHidTransport::~BtHidTransport()
{
} // destructor
This is base class, now we have derived class header:
bthidtransportfixes.h:
#include "bthidtransport.h"
class BtHidTransportFixes : public BtHidTransport
{
BtHidTransportFixes(); // constructor
virtual ~BtHidTransportFixes(); // destructor
} // BtHidTransportFixes
However, in particular project, BtHidTransportFixes has no implementation (.cpp) file. The project itself builds without errors. If I instantiate new object at runtime from class with:
BtHidTransport* createdObject=new BtHidTransportFixes();
and BtHidTransportFixes has no implementation (.cpp) file, what is the order of execution in terms to parent class? I am using Eclipse 4.3.2 for Windows (host OS is Windows 7 64bit Ultimate) with ARM DS-5 5.20.2 compiler. There is no implementation of BtHidTransportFixes
anywhere in the project, I've searched for it in ALL projects files. Compiler optimizations are turned off with -O0 flags explicitly. Here is assembler listing of build process:
;;;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
and linker ouput:
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
The size of constructor seems to be 0, what exaclty is executed here? And to simplify out, I've deliberately deleted parameters of constructor (here, in StackOverflow description of issue), is this my bad?
解决方案
It doesn't have to fail to build. Even though a virtual member function is implicitly used under the one definition rule.
[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.
Your tool-chain does not have to warn about it, or fail to build. It can pretend all is well. The program is plain ill-formed in that case. If the tool-chain manages to get around the problem, or not diagnose it until a runtime crash occurs, it's all within the contract.
推荐阅读
- javascript - TypeScript VueJS:使用具有计算属性的观察器
- html - 仅在顶部使用蒙版在 div 上自定义顶部边框
- c++ - 如何将 WM_GESTURE 消息转发/处理到不同的窗口
- c# - 将动态 json 对象反序列化为类
- c - 从 C 转换为 Racket 方案
- maintenance-mode - 目标组中没有健康实例时的维护页面
- arrays - 为什么变量的值在程序中改变而不改变?
- php - 我想将记录从 SQL 导入 Excel
- mysql - 选择具有回退空记录的行
- javascript - 有没有办法让我的 JavaScript 文件不在 html 页面中运行?