Классы C++: концептуальный класс-двойник: LNK2005

Шиш. Я столкнулся с печально известной ошибкой LNK2005 при определении своего класса и, похоже, не могу решить проблему.

(Я разрываю на части свой столь же печально известный синглтон, чтобы хорошо отразить организацию.) Первоначальный упомянутый синглтон был закодирован... ...таким отличным, блестящим способом... чтобы избежать всех принципов C++ OPP и концепции, о которых я не знал в то время, но это сработало! ....Как-то. Хотя какая-то случайность простейших концепций C++ все же была. Теперь мне нужна организация, скорость компиляции и продвинутые методы структурирования, чтобы заставить его работать быстро, и вы это понимаете.

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

Кроме того, я соответственно использовал директивы препроцессора. Но что-то все равно остается не так.

Примечание (редактировать): я переписал вопрос, чтобы указать указанную ошибку.

Рассмотреть возможность:

D3D.h

#include "Infinity.h"
class Direct3D :
public Infinity
{
public:
    Direct3D();
    ~Direct3D();
    IDXGISwapChain                  *Swapchain; //Display modes.
    static ID3D11Device             *Device;
    static ID3D11DeviceContext      *DeviceContext;
    static ID3D11RenderTargetView   *RenderTargetView;
     
    void D3D_Start(float width, float height);
    void D3D_Render();
    void D3D_Terminate();
    void ViewPort(float Height, float Width, float MaxDepth, float MinDepth, float TopLeftX, float TopLeftY);
}Direct3D;

...и Windows.h

#include "Infinity.h"
class Windows :
public Infinity
{
    public:
    Windows();
    ~Windows();
    bool DisplayWindow(int width, int height, HINSTANCE hInstance);
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
}Windows;

Наконец, Infinity.h

#pragma once

class Infinity{
public:
Infinity();
~Infinity();

static HWND hWnd;
};

Принимая во внимание, что все реализации находятся в соответствующих файлах .cpp. Помимо #pragma, я использовал #ifndef ... #endif. Я подозреваю, что могу непреднамеренно вызывать некую реализацию, автоматически инициализируя классы в их заголовочных файлах. Но это выглядит безумно кошерно и позволяет мне объявлять функции-члены как:

Direct3D.D3D_Start() без указания статического члена, Direct3D::D3D_Start(). Должны ли мои заголовки быть статическими?

Редактировать: ниже файл .cpp:

#include "stdafx.h"
#include "Infinity.h"
#include "Windows.h"
#include "Direct3D.h"

MSG     msg;
float width = 1024;
float height = 768;

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    windows.DisplayWindow(1280, 900, hInstance);
    direct3D.D3D_Start(width, height);
    direct3D.ViewPort(height, width, 1.0f, 0.0f, 0, 0);
    while (WM_QUIT != msg.message){
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else{
            direct3D.D3D_Render();
        }
    }
    direct3D.D3D_Terminate();
    return msg.wParam;
}

* Обновление .cpp было изменено, чтобы показать решение Найла. Редактировать:

Вопрос:

Я получаю проблему LNK2005, потому что я автоматически инициализировал свои классы в их файлах заголовков, учитывая решение вопроса о переполнении стека:

Ошибки VS 2010 C++ LNK2005 при использовании #pragma Once и #ifndef

Что, похоже, не работает, основанное на моем понимании решения.

Компилятор

VS2013 возвращает:

Error 1 error LNK2005: "class Direct3D Direct3D" (?Direct3D@@3V0@A) already defined in Direct3D.obj C:\Users\InfinityMachine\documents\visual studio 2013\Projects\Win32Project3\Win32Project3\Win32Project3.obj Win32Project3

Error 2 error LNK2005: "class Windows Windows" (?Windows@@3V0@A) already defined in Win32Project3.obj C:\Users\InfinityMachine\documents\visual studio 2013\Projects\Win32Project3\Win32Project3\Windows.obj Win32Project3

Error 3 error LNK1169: one or more multiply defined symbols found C:\Users\InfinityMachine\documents\visual studio 2013\Projects\Win32Project3\Debug\Win32Project3.exe 1 1 Win32Project3


person Rashid Ellis    schedule 31.08.2014    source источник
comment
Вообще не понятно, что вы спрашиваете.   -  person R Sahu    schedule 31.08.2014
comment
@RSahu Я отредактировал основной вопрос для уточнения.   -  person Rashid Ellis    schedule 31.08.2014
comment
I must declare multiple .cpp files Файл .cpp не объявляется. Один объявляет класс, функцию или переменную. Should my headers all be static? Статического заголовка не существует. Есть статические члены класса. Main.h Где находится Infinity.h? Am I getting the LNK2005 issue Без списка ошибок, которые вы получаете (дословно!) и без MCVE (обратите внимание, что все буквы важны), мы можем только делать необоснованные предположения.   -  person n. 1.8e9-where's-my-share m.    schedule 31.08.2014
comment
@н.м. Примечание. Файлы .ccp не были объявлены программно; они были реализованы. Заголовки не были статичными, члены класса внутри них были, подразумевая, что если x::y(), static y. Как говорит человеческий язык, смесь метафорических символов и явных определений использовалась одновременно для описания проблемы, вплетая идиомы биологической прошивки в английский язык. Вопрос был отредактирован для дальнейшего уточнения.   -  person Rashid Ellis    schedule 01.09.2014
comment
Почему вы сразу объявляете class Direct3D... } Direct3D и одноименную переменную? Это может быть причиной ошибки.   -  person Niall    schedule 01.09.2014
comment
@Niall Это должен быть ответ.   -  person n. 1.8e9-where's-my-share m.    schedule 01.09.2014


Ответы (1)


Вы сразу объявляете class Direct3D... } Direct3D; и переменную с таким же именем. Это будет причиной такой ошибки.

Переменная типа Direct3D с именем Direct3D (или другим именем) будет в каждой единице перевода, которая включает этот заголовок, то же самое относится и к Windows.

Одно из возможных решений — удалить объявление переменной, другое — переместить его и сделать статическим или в анонимном пространстве имен. Альтернативы включают extern или реализацию синглтона; что может быть ближе к первоначальному замыслу.

Основываясь на дальнейших обсуждениях, подходящим решением здесь является;

class Direct3D {}; 
extern Direct3D direct3D;

Затем в одном из файлов реализации

Direct3D direct3D;

Затем он объявляет объект как extern и предоставляет его единственный экземпляр.

person Niall    schedule 31.08.2014
comment
Изменение непосредственного объявления с Direct3D на direct3D привело к аналогичному результату: Error 1 error LNK2005: "class Direct3D direct3D" (?direct3D@@3VDirect3D@@A) already defined in Direct3D.obj C:\Users\InfinityMachine\documents\visual studio 2013\Projects\Win32Project3\Win32Project3\Win32Project3.obj Win32Project3 Вопрос был отредактирован, чтобы показать основной .cpp. - person Rashid Ellis; 01.09.2014
comment
Ошибка не в имени переменной, а в том, где она находится. Попробуйте static Direct3D Direct3D; после объявления класса. - person Niall; 01.09.2014
comment
Если в другом месте он не нужен, сделайте объект Direct3D локальным для функции _tWinMain. - person Niall; 01.09.2014
comment
The error is not the name of the variable,... Я должен сделать это в реализации? - person Rashid Ellis; 01.09.2014
comment
Правильный. Я бы так подумал, да. - person Niall; 01.09.2014
comment
If not needed elsewhere, make the Direct3D object local to... Я надеялся сохранить эти значения внутри класса Direct3D без локального экземпляра. В основном с помощью дескриптора автоматического экземпляра. Это плохо? - person Rashid Ellis; 01.09.2014
comment
Давайте продолжим обсуждение в чате. - person Niall; 01.09.2014
comment
Реальная ситуация такова, что эта переменная вообще не нужна. - person n. 1.8e9-where's-my-share m.; 02.09.2014
comment
@н.м. Вполне возможно, это было предложено, но ОП не интересовался местным. Похоже, это тоже был процесс рефакторинга. - person Niall; 02.09.2014