Jak poprawnie zdefiniować enum w pliku nagłówkowym?

0

Cześć,
kolejny dzień, kolejny błąd (a w zasadzie już siedzę nad nim parę dni). Próbuję zainicjalizować klasę enum wartościami, ale coś mi nie idzie. Głupi jestem, bo jakoś na samym początku to działało, ale nie wrzuciłem kodu na repo i po dodaniu nowego kodu już nie działa i nie wiem czemu XD. Sytuacja wygląda tak: chcę zainicjalizować w przestrzeni nazw pola, aby wszędzie w projekcie był do nich dostęp, ale w plikach, w których używam enum dostaję błędy, że pola są już zdefiniowane w pliku implementacyjnym klasy:
jakiś_plik.obj : error LNK2005: "enum Game::Color Colours::red" (?red@Colours@@3W4Color@Game@@A) already defined in Game.obj
Game.h:

class Game final {
public:
	explicit Game() noexcept;
	enum class Color { red, blue, green, yellow };
	static void setConsoleTextColoured(const Color&);
	static void setConsoleTextDefault();
        //...
};

namespace Colours {
    Game::Color red = Game::Color::red;
	Game::Color blue = Game::Color::blue;
	Game::Color green = Game::Color::green;
	Game::Color yellow = Game::Color::yellow;
}

Game.cpp:

#include "Game.h"
void Game::setConsoleTextColoured(const Color& color) { //to jest jedyna metoda, która ma jakikolwiek związek z enum w pliku implementacyjnym.
	consoleColorHandle::hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	switch (color) {
		case Game::Color::red: SetConsoleTextAttribute(consoleColorHandle::hOut, 12); break;
		case Game::Color::green: SetConsoleTextAttribute(consoleColorHandle::hOut, 10); break;
		case Game::Color::blue: SetConsoleTextAttribute(consoleColorHandle::hOut, 11); break; 
		case Game::Color::yellow: SetConsoleTextAttribute(consoleColorHandle::hOut, 14); break;
	}
}

jakiś_plik.cpp:

Game::setConsoleTextColoured(Colours::red); //przykładowe użycie metod w dowolnym pliku.
Game::setConsoleTextDefault();

domyślam się, że problem leży w tym, że są to statyczne metody i po prostu pola nie są zdefiniowane(?) w czasie kompilacji. Tylko jak je teraz zdefiniować tak, aby były widoczne w całym projekcie?
Dzięki, pozdro.

2

Problem polega na tym, że definiujesz zmienne w pliku nagłówkowym, przez co potem każdy plik, który dołącza ten nagłówek, będzie miał kopię tych zmiennych.
Ogólnie ten pomysł, żeby mieć te kolory w Colours jest dziwny (nie mówiąc już o mieszaniu brytyjskiego z amerykańskim). Skoro jakaś funkcja ma dostęp do klasy Game, to będzie miał dostęp do Game::Color.

1

Po co ci ta cześć?

namespace Colours {
    Game::Color red = Game::Color::red;
    Game::Color blue = Game::Color::blue;
    Game::Color green = Game::Color::green;
    Game::Color yellow = Game::Color::yellow;
}

To jest nadmiar formy nad treścią.
Jak już to dodaj constexpr i problem rozwiązany:

namespace Colours {
    constexpr auto red = Game::Color::red;
    constexpr auto blue = Game::Color::blue;
    constexpr auto green = Game::Color::green;
    constexpr auto yellow = Game::Color::yellow;
}
0

Dziękuję @twonek i @MarekR22 !
Rzeczywiście jak ja mogłem o takiej rzeczy zapomnieć! Usunąłem z headera deklaracje i przerzuciłem je do anonimowego namespace (skoro Colours był dziwny :P) i zadziałało :)
Nawet nie wiedziałem, że można constexpr łączyć z enum, więc zapamiętam. Dzięki wielkie.

0

@Cyberah A gdzie include guard/pragma once w pliku *.h?

0

Strasznie a usilnie próbujesz udziwniać swój kod – to nie pierwszy tego typu twój wątek z wynalezionym problemem...
Do czego ci to osobne namespace Colours?

0

@Azarien: Zwykłe eksperymentowanie w Cpp + słaba jego znajomość (albo po prostu za krótki staż) powodują takie wynalazki. Generalnie, to jest mój pierwszy większy projekt no i zdarza się.

Już nie ma namespace Colours, tylko jest anonimowy. Zmieniłem, bo dla innych to jest dziwne, a podczas pisania kodu myślałem, że to poprawi czytelność (aczkolwiek nie za bardzo). Mam taką prośbę - mógłbyś wytłumaczyć też dlaczego nazwałeś to udziwnianiem?

1 użytkowników online, w tym zalogowanych: 0, gości: 1