首页 > 解决方案 > 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?

标签: c++ooparmcross-compiling

解决方案


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.


推荐阅读