VS 2008 раздражающая копия конструктора ссылки зависимость - PullRequest
2 голосов
/ 07 апреля 2010

Я столкнулся со следующим раздражающим и, казалось бы, некорректным поведением в компиляторе Visual Studio 2008 C ++:

Предположим, у меня есть библиотека классов - Car.lib, которая использует класс "Car", сзаголовок под названием "Car.h":

class Car
{
    public:
    void Drive()
    {
        Accelerate();
    }

    void Accelerate();
};

На самом деле я пытаюсь использовать заголовки Car (для некоторых других функций), но без необходимости связываться с самим Car.lib (фактическимкласс не называется "Car", но я очищаю этот пример).

Если я #include "Car.h" в файле .cpp, который используется для создания управляемого C ++ .dll, но никогда не ссылаюсь на Car,все компилируется и ссылки нормально.Это потому, что я никогда не создаю экземпляр объекта Car.

Однако, следующее:

namespace {
    class Car
    {
    public:
         Car(const Car& rhs)
         {
              Accelerate();
         }

         void Accelerate();
    };
}

оставляет меня с ошибкой связи:

Error 2 error LNK2001: unresolved external symbol "public: void __thiscall `anonymous     namespace'::Car::Accelerate(void)" (?Accelerate@Car@?A0xce3bb5ed@@$$FQAEXXZ) CREObjectWrapper.obj CREObjectBuilderWrapper

Примечаниеобъявил все это в анонимном пространстве имен, так что ни в коем случае нельзя экспортировать функции Car из .DLL.

Я могу категорически гарантировать, что Car нигде больше не упоминается, потому что я только что сделал этокласс и набрал в определении от Scatch.«Настоящий» класс - это другое имя.

Объявление конструктора копирования вне строки не имеет значения.то есть следующее также не может связать:

class Car
{
    public:
    Car(const Car& rhs);
    void Accelerate();
};

Car::Car(const Car& rhs)
{
    Accelerate();
}

Это что-то особенное, что связано с примечанием конструктора копирования, потому что следующее, например, делает ссылку:

class Car
{
    public:
    Car()
    {
        Accelerate();
    }
    void Accelerate();
};

Я не гуру стандартов C ++, но мне это кажется неправильным.Конечно, компилятору по-прежнему не нужно было даже генерировать какой-либо код, который вызывает конструктор Car copy.

Может кто-нибудь подтвердить, правильно ли это поведение?Прошло много времени с тех пор, как я использовал C ++ - но я не думаю, что это, например, проблема с Visual Studio 6.0.

Это может быть потому, что я создаю управляемый C ++ .dll. (Позже: да, именно в этом проблема. Параметр / clr вводит эту зависимость).

Вот командная строка, используемая для создания проекта:

/OUT:"..\..\bin\Release\CREObjectBuilderWrapper.dll" /INCREMENTAL:NO /NOLOGO /LIBPATH:"..\..\lib\qa\lib" /LIBPATH:"..\..\lib\release" /LIBPATH:"..\..\lib\VDB" /DLL /MANIFEST /MANIFESTFILE:"Release\ObjectBuilderWrapper.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"c:\Release\ObjectBuilderWrapper.pdb" /LTCG /DYNAMICBASE:NO /FIXED:No /MACHINE:X86 /KEYFILE:"c:\src\ObjectBuilderWrapper\\FI.snk" /ERRORREPORT:PROMPT CRERuntime.lib QA.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

Может кто-нибудь предложить обходной путь, который позволяет «повторно использовать» метод Accelerate из конструктора копирования и при этом конструктор копирования объявлен встроенным?

Ответы [ 3 ]

1 голос
/ 07 апреля 2010

Я попытался скомпилировать ваш пример с VS2008 в нативный проект; совершенно никаких проблем. Но затем я попробовал в управляемом проекте, и я получил ту же ошибку. Так что это явно связано с управляемым кодом.

Поскольку C ++ / CLI является расширением вне стандарта, мы не должны удивляться тому, что он делает некоторые неожиданные вещи. К сожалению, я не могу указать причину, по которой управляемая среда должна запускать конструктор копирования, к сожалению.

0 голосов
/ 07 апреля 2010

Только что опробовал ваш код в анонимном пространстве имен с VS2008, и он прекрасно компилируется и связывается.

Убедитесь, что вы действительно не обращаетесь к Car.

Что произойдет, еслиВы полностью удалили определение Car?все еще компилируется?

0 голосов
/ 07 апреля 2010

Ну, похоже, что-то нуждается в конструкторе копирования, но не нужен конструктор по умолчанию. Примером этого может быть:

std::vector <Car> v;

независимо от того, действительно ли вы его заполняете.

...