производный класс без файла реализации (.cpp) - PullRequest
0 голосов
/ 06 февраля 2019

В проекте, который я унаследовал от coworker, у меня есть базовый класс 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 для Windows (хост-ОС Windows 7 64bit Ultimate ) с ARM DS-5 5.20.2 компилятором.Нигде в проекте нет реализации BtHidTransportFixes, я искал ее в ВСЕ файлы проектов .Оптимизация компилятора отключена с -O0 flags явно .Вот список ассемблера процесса сборки:

;;;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), это плохо?

Ответы [ 3 ]

0 голосов
/ 06 февраля 2019

Это не должно быть невозможно построить.Даже если виртуальная функция-член неявно используется в соответствии с правилом одного определения.

[basic.def.odr] (выделено мной)

4 Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе с помощью odr, кроме исключенного оператора; Диагностика не требуется .Определение может явным образом появиться в программе, оно может быть найдено в стандартной или пользовательской библиотеке, или (при необходимости) оно неявно определено (см. [Class.ctor], [class.dtor] и [class.copy).]).Встроенная функция или переменная должна быть определена в каждой единице перевода, в которой она используется odr, вне отброшенного оператора.

Ваша цепочка инструментов не должна предупреждать об этом или не может создать,Можно делать вид, что все хорошо.Программа в этом случае просто плохо сформирована.Если цепочке инструментов удается обойти проблему или не диагностировать ее до тех пор, пока не произойдет сбой среды выполнения, это все в рамках контракта.

0 голосов
/ 06 февраля 2019

Я нашел решение для конкретной проблемы.Файл процесса сборки ( .inc ) получает указание заменить файл заголовка bthidtransportfixes.h на исправленный bthidtransportfixes.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 , чтобы включитьпатч, добавил новый файл реализации для процесса сборки, и теперь он работает как шарм.

0 голосов
/ 06 февраля 2019

Если в программе отсутствуют реализации объявленных функций-членов, выполнение вообще не выполняется - компоновщик не сможет создать исполняемый файл.

Единственное, в чем не имеют значения реализации, это есликласс никогда не используется.В этом случае компоновщик никогда не будет вынужден искать реализацию.

Но если ваша программа содержит - как вы заявляете - следующую строку

DerivedClass* derivedClass=new DerivedClass();

, программа некорректна(и компоновщик должен пожаловаться).

...