2013-02-22 10 views
7

my_test.hCzy zmienna statyczna const powinna zostać zainicjowana w pliku nagłówkowym C++?

#ifndef MY_TEST 
#define MY_TEST 

struct obj { 
    int x; 
    int y; 
}; 

class A { 
private: 
    const static int a=100; 
    const static obj b; 
}; 

const obj A::b={1,2}; 

#endif 

Kompilując CPP za pomocą tego pliku nagłówka, błąd 'multiple definition of 'A::b' występuje.

  1. Dlaczego tak jest, gdy korzystam już z makra zabezpieczającego?
  2. dlaczego A::a nie produkuje erro? (Nie mogę napisać kod const static obj b={1,2} w class A)

Odpowiedz

4

dlaczego tak jest, gdy już korzystam z makra zabezpieczającego?

strażnicy Header tylko uniemożliwić włączenie zawartości pliku nagłówka więcej niż raz w tym samym translation unit nie na wielu jednostek tłumaczeniowych.

dlaczego A::a nie ma komunikatu o błędzie (nie mogę napisać kod const static obj b={1,2} w class A)

In-class initialization jest dozwolona przez kompilator jako przypadek szczególny dla członków danych statycznych typu literalnego const. Twój przykład to inicjowanie w klasie.

const A::b definiuje samą nazwę symbolu w każdej jednostce tłumaczeniowej, gdzie nagłówek zostanie włączone, a tym samym łamie one definition rule.

Musisz przenieść definicję do jednego i tylko jednego pliku źródłowego cpp, aby został zdefiniowany tylko jeden raz.

+2

Dla OP, jako początkującego, "Musisz" jest poprawne. Jednak jako bezwzględne oświadczenie techniczne nie jest, ponieważ istnieje wyjątek ODR dla szablonów klas. Co oznacza, że ​​pod względem technicznym, jeśli istnieje taka potrzeba, można zdefiniować stałą statyczną w szablonie klasy, a następnie dziedziczyć z dowolnej specjalizacji. Jest to czasami określane jako szablonowy ciągły trick. Bardziej praktycznym sposobem uniknięcia pliku implementacji jest zapewnienie dostępu do stałej za pośrednictwem funkcji inline (która może mieć stałą jako lokalna). " –

+0

@Alf: Zgadzam się na Twój komentarz. W rzeczywistości jest to dobra informacja. –

0

Problemem jest twoja definicja A::b nie zawiera typ. Być poprawnej definicji, powinno być:

const obj A::b = {1, 2}; 

To będzie pozbyć się błędu kompilacji, ale wciąż pojawiają się błędy linkera jeśli to ten nagłówek w więcej niż jednym pliku źródłowym, ponieważ A::b będzie mnoży się następnie. Powinieneś przenieść definicję do pliku .cpp.

0

Bez względu na to, czy masz osłonę nagłówka, czy nie, umieszczenie tej inicjalizacji w pliku nagłówkowym będzie oznaczać, że otrzymasz wystąpienie A::b w każdym pliku źródłowym, który zawiera ten plik nagłówkowy. Stąd błąd łącznika.

Ogólnie rzecz biorąc, jest to możliwe, ale nie jest to dobry pomysł.

1

Alok już odpowiedział na to pytanie, ale oto kilka prostych zasad kciuk, w łatwej do zapamiętania formie:

  1. Deklaracje iść w pliku .h
  2. Definicje idź w.cpp plik

Dlatego członkowie statyczne muszą być zadeklarowanew pliku .h, a następnie zdefiniowane w pliku .cpp. W twoim przypadku popraw składnię deklaracji, a następnie przenieś ją do pliku "my_test.cpp".

Powiązane problemy