zmienne stałe nie działające w nagłówku
Jeśli zdefiniuję moje stałe zmienności w nagłówku w ten sposób...
extern const double PI = 3.1415926535;
extern const double PI_under_180 = 180.0f / PI;
extern const double PI_over_180 = PI/180.0f;
Otrzymuję następujący błąd
1>MyDirectX.obj : error LNK2005: "double const PI" (?PI@@3NB) already defined in main.obj
1>MyDirectX.obj : error LNK2005: "double const PI_under_180" (?PI_under_180@@3NB) already defined in main.obj
1>MyDirectX.obj : error LNK2005: "double const PI_over_180" (?PI_over_180@@3NB) already defined in main.obj
1>MyGame.obj : error LNK2005: "double const PI" (?PI@@3NB) already defined in main.obj
1>MyGame.obj : error LNK2005: "double const PI_under_180" (?PI_under_180@@3NB) already defined in main.obj
1>MyGame.obj : error LNK2005: "double const PI_over_180" (?PI_over_180@@3NB) already defined in main.obj
Ale jeśli usunę te stałe z nagłówka i umieszczę je w dokumencie, który zawiera nagłówek w ten sposób...
const double PI = 3.1415926535;
const double PI_under_180 = 180.0f / PI;
const double PI_over_180 = PI/180.0f;
It works
Czy ktoś wie, co robię źle ??Dzięki
10 answers
Problem polega na tym, że definiujesz obiekty z linkami zewnętrznymi w pliku nagłówkowym. Spodziewamy się, że po dołączeniu tego pliku nagłówkowego do wielu jednostek tłumaczeniowych, otrzymasz wiele definicji tego samego obiektu z połączeniem zewnętrznym, co jest błędem.
Właściwy sposób, aby to zrobić, zależy od twoich intencji.
(1) możesz umieścić swoje definicje w pliku nagłówkowym, ale upewnij się, że mają one wewnętrzne połączenie .
In C that would wymagaj wyraźnego static
static const double PI = 3.1415926535;
static const double PI_under_180 = 180.0f / PI;
static const double PI_over_180 = PI/180.0f;
W C++ static
jest opcjonalne (ponieważ w C++ const
obiekty mają domyślnie wewnętrzne powiązania)
const double PI = 3.1415926535;
const double PI_under_180 = 180.0f / PI;
const double PI_over_180 = PI/180.0f;
(2) można też umieścić zwykłe deklaracje nie definiujące w pliku nagłówkowym i umieścić definicje W Jednym (i tylko jednym) pliku implementacji
Deklaracje w pliku nagłówek muszą zawierać jawne extern
i No initializer
extern const double PI;
extern const double PI_under_180;
extern const double PI_over_180;
I definicje w jednym implementacja plik powinien wyglądać następująco
const double PI = 3.1415926535;
const double PI_under_180 = 180.0f / PI;
const double PI_over_180 = PI/180.0f;
(jawne extern
w definicjach jest opcjonalne, jeśli powyższe deklaracje poprzedzają definicje w tej samej jednostce tłumaczeniowej).
To, którą metodę wybierzesz, zależy od twoich intencji.
Pierwsza metoda ułatwia kompilatorowi optymalizację kodu, ponieważ widzi rzeczywistą wartość stałej w każdej jednostce tłumaczenia. Ale jednocześnie koncepcyjnie dostajesz osobne, niezależne stałe obiekty w każdej jednostce tłumaczeniowej. Na przykład &PI
będzie oceniać pod innym adresem w każdej jednostce tłumaczenia.
Druga metoda tworzy prawdziwie globalne stałe, tzn. unikalne obiekty stałe, które są współdzielone przez cały program. Na przykład &PI
będzie oceniać pod tym samym adresem w każdej jednostce tłumaczenia. Ale w tym przypadku kompilator widzi tylko rzeczywiste wartości w jednej i tylko jednej jednostce tłumaczenia, co może utrudnić optymalizację.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-01 01:11:16
extern
oznacza to, że 'prawdziwa' definicja zmiennej znajduje się gdzie indziej, a kompilator powinien ufać, że rzeczy będą się łączyć w czasie połączenia. Posiadanie definicji w jednej linii z extern
jest dziwne i jest tym, co zmaga się z Twoim programem. Jeśli chcesz, aby były extern
, po prostu zdefiniuj je dokładnie raz gdzie indziej w swoim programie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-24 19:02:55
Klasa przechowywania dla nich jest prawie na pewno przyczyną problemu, który widzisz. Jeśli go usuniesz, kod prawdopodobnie będzie w porządku (przynajmniej pod tym względem).
Edit: właśnie zauważyłem, że otagowałeś to jako C i C++. Pod tym względem C i C++ są naprawdę bardzo różne (ale z komunikatów o błędach, najwyraźniej kompilujesz jako C++, a nie C). W C++, chcesz usunąć extern
, ponieważ (domyślnie) zmienne const
mają klasę przechowywania static
. To znaczy każdy plik źródłowy (Jednostka tłumaczenia) otrzyma własną "kopię" zmiennej i nie będzie konfliktu między definicjami w różnych plikach. Ponieważ (prawdopodobnie) używasz tylko wartości, nie traktując ich jako zmiennych, posiadanie wielu "kopii" niczego nie zaszkodzi-żadna z nich nie zostanie przydzielona przestrzeń dyskowa.
W C, extern
jest raczej inne, a usunięcie extern
nie zrobi żadnej rzeczywistej różnicy, ponieważ będą one domyślnie extern
. W takim przypadku naprawdę musisz zainicjalizuj zmienne dokładnie w jednym miejscu i zadeklaruj je w nagłówku. Alternatywnie, możesz dodać static
klasę pamięci, którą C++ będzie dodawać domyślnie, gdy / jeśli usuniesz extern
z nagłówka.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-24 19:09:28
Wygląda na to, że plik nagłówka jest dołączany wiele razy. Musisz dodać strażników.
Na górze KAŻDEGO pliku nagłówkowego powinieneś mieć coś w stylu:
#ifndef MY_HEADER_FILE_NAME_H
#define MY_HEADER_FILE_NAME_H
...
// at end of file
#endif
Jeśli używasz g++ lub MSVC, możesz po prostu dodać:
#pragma once
Na górze KAŻDEGO pliku nagłówkowego, ale nie jest on w 100% przenośny.
Ponadto nie należy definiować stałych w plikach nagłówkowych, tylko deklarować je:
// In header file
extern const int my_const;
// In one source file
const int my_const = 123;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-24 19:04:05
Problem polega na tym, że inicjalizujesz zmienne w pliku nagłówkowym ; tworzy to deklarację definiującą , która jest powtarzana w każdym pliku zawierającym ten nagłówek,stąd błąd wielokrotnej definicji.
Chcesz nie -definiującą deklarację (bez inicjalizacji) w pliku nagłówkowym i umieść definiującą deklarację w jednym z plików implementacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-24 19:59:25
Wiele błędnych odpowiedzi poniżej. Te, które są poprawne, to te, które każą Ci usunąć extern
, jak powiedział sellibitze w swoim komentarzu, są poprawne.
Ponieważ są one zadeklarowane const, nie ma problemu z definicją w nagłówku. C++ będzie wstawiać const dla typu wbudowanego, chyba że spróbujesz pobrać jego adres (wskaźnik do const), w którym to przypadku utworzy on instancję za pomocą połączenia static
, możesz wtedy również uzyskać wiele instancji w oddzielnych Moduły, ale jeśli nie oczekujesz, że wszystkie wskaźniki do tego samego const będą miały ten sam adres, nie jest to problemem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-24 21:01:10
Musisz zadeklarować kontanty w nagłówku, a następnie zdefiniować je w jednym z plików kodu. Jeśli nie zadeklarujesz ich nigdzie, wtedy wystąpi błąd linkera, gdy próbuje powiązać deklarację z rzeczywistą definicją. Możesz także użyć poleceń # ifdef, aby mieć jedną definicję w nagłówku.
Upewnij się, że są zadeklarowane w nagłówku, który jest dołączany przez wszystkich, którzy ich potrzebują i upewnij się, że są zdefiniowane dokładnie raz.
Jakub
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-24 19:02:28
Jeśli chcesz zdefiniować stałe w plikach nagłówkowych, użyj static const
. Jeśli użyjesz extern
, linker ma prawo narzekać na wiele definicji, ponieważ każdy plik źródłowy, w tym plik źródłowy, dostarczy pamięci dla zmiennej, jeśli przypiszesz wartość.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-24 19:03:39
W deklarowaniu global const w nagłówku powoduje, że każda jednostka kompilacji zawierająca ten hader będzie miała własne definicje globalne definicje o tej samej nazwie. Więc linker tego nie lubi.
Jeśli naprawdę potrzebujesz ich w nagłówku, prawdopodobnie powinieneś zadeklarować je jako statyczne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-24 19:04:26
Stare pytanie, rzeczywiście, ale brakuje jednej użytecznej odpowiedzi.
Możliwe jest nakłonienie MSVC do zaakceptowania stałych statycznych w nagłówkach, po prostu zawijając je w "atrapowy" szablon klasy:
template <typename Dummy = int>
struct C {
static const double Pi;
};
template <typename Dummy = int>
const double C<Dummy>::Pi = 3.14159;
Teraz, C:: PI można uzyskać dostęp z innego miejsca. Żadna redefinicja nie narzeka; stała jest bezpośrednio dostępna w każdej jednostce kompilacji bez wymyślnej optymalizacji czasu łącza. Makro może być rozwijane w celu dalszego ulepszenia tego podejścia (nawet jeśli makra są złe).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-24 04:31:56