Składowe statyczne i ich inicjalizacja

0

Witam, jak to jest ze statycznymi składowymi klas? Zakładając, że mamy taki kod:

 
#include <iostream>
using namespace std;

static p;

class Klasa
{
public:
        static int n;
};

int Klasa::n = 2;             // ta linijka jest niezbędna do kompilacji programu

int main (void)
{
    cout<<Klasa::n<<endl;    //  n=2
    cout<<Klasa::p<<endl;    //  p=0
    return 0; 
}

Wiem, że inicjalizowane wewnątrz klasy mogą być tylko składowe statyczne CONST. Pamiętam również, że zmienne statyczne niezainicjalizowane otrzymują wartość 0;
To czemu ja muszę inicjalizować tą składową statyczną, skoro składowe statyczne otrzumują wartość 0 domyślnie? Mógłby mi ktoś to wyjaśnić? Z góry wielkie dzięki

0

Podobne pytanie mam także gdy szablony klas posiadają statyczne składowe:

 
// tmp2tmp.cpp -- Szablony zaprzyjaŸnione z szablonem klasy
#include <iostream>
using namespace std;

// Szablon klasy
template <typename TT>
class Klasa
{
public:
   TT item;
   static int ct;
public:
   Klasa(const TT & i) : item(i) { ct++; }
   ~Klasa() { ct--; }
};

template <typename TT>
int Klasa<TT>::ct = 0;

//Klasa<int>::ct=0;         // niepoprawne
//Klasa<double>::ct=0;      // niepoprawne

int main()
{


   return 0;
}


Czy mógłby mi ktoś także wytłumaczyć, czemu te dwe linijki inicjalizacji są niepoprawne? Bo gdybym chciał, żeby np. specjalizacja szablonu dla typu int, posiadała początkową wartość składowej statycznej równą 0, a specjalizacja szablonu dla typu int, posiadała początkową wartość składowej statycznej równą 10? Również wielkie dzięki i za tą odpowiedź :)

P.S. Do pierwszego postu zapomniałem się zalogowac :P Ale to też ja ....

1

Będzie równa 0, jeżeli niczego nie podasz. Najważniejsza jest ta część po lewej stronie znaku = czyli definicja. Statyczny składnik klasy musi mieć definicję. Jeżeli dodasz coś po = to będzie definicja z inicjalizacją, ale to definicja jest kluczowa.

Co do szablonów to zapisuje się to tak samo jak każdą specjalizację czyli: template<> Typ Klasa<Specjalizacja>::zmienna = wartosc. Kompilator musi wiedzieć, że chodzi Ci o specjalizację szablonu, więc template dalej musi być.

Tu masz przykład:

#include <iostream>

using namespace std;

class X {
public:
  static int x;
};

// Teraz X::x bedzie rowne 0.
int X::x;

template <typename T>
class Y {
public:
  static int y;
};

template <typename T>
int Y<T>::y = 10;

// Specjalizacja wyglada tak:
template<>
int Y<double>::y = 20;

int main() {
  cout << X::x << '\n';
  cout << Y<int>::y << '\n';
  cout << Y<double>::y << '\n';
	
  return 0;
}

http://ideone.com/EQSQg

0

Co do pierwszego - jest tak dlatego, że w klasie masz tylko deklaracje, a ta linijka poza klasą jest definicją i potrzebuje ją nie kompilator, ale linker, który łączy to wszystko do kupy. Wystarczyłoby mu nawet int Klasa::n;

Co do drugiego, masz po prostu błąd w składni. Najpierw musi być typ, potem nazwa zmiennej, więc powinno to wyglądać tak: int Klasa<int>::ct = 0;

//zostałem wyprzedzony :p

0

Acha, ja myślałem, że samo to że już sama definicja klasy powoduje także zdefiniowanie statycznej składowej klasy.

0

Witamy w świecie C++, gdzie wiele rzeczy nie jest takie jakie się wydaje, jak to ktoś powiedział, gdzie walczysz z trudnościami nieznanymi innym językom :p

0

Teraz czaje, wielkie dzięki :)

0

Z tym, że brakuje tam typu to fakt, błąd, ale nie wpadłbym na to, że potrzebny mi jeszcze nagłówek typename..

0
matieti napisał(a):

Z tym, że brakuje tam typu to fakt, błąd, ale nie wpadłbym na to, że potrzebny mi jeszcze nagłówek typename..

Kompilator musi wiedzieć, że chodzi Ci o szablon. W zasadzie to jest potrzebne tylko template<>, w taki sposób określa się, że teraz będziesz pisał o specjalizacji.

0

Tak tak, tylko do było dla mnie jakby dość logiczne, że skoro podaje nazwę klasy i w nawiasach trójkątnych typ, no to to musi być szablon :P Widać nie dal kompilatora:P

0
Endrju napisał(a):
matieti napisał(a):

Z tym, że brakuje tam typu to fakt, błąd, ale nie wpadłbym na to, że potrzebny mi jeszcze nagłówek typename..

Kompilator musi wiedzieć, że chodzi Ci o szablon. W zasadzie to jest potrzebne tylko template<>, w taki sposób określa się, że teraz będziesz pisał o specjalizacji.

Hmm, skoro już występuje użycie Klasa<int> to kompilator powinien tą klasę stworzyć i samo int Klasa<int>::ct = 10; powinno mu wystarczyć. Kompilatorowi w VS wystarcza.

0

racja, ja próbowałem to najpierw na Code::Blocks. Dzieki, że powiedziałeś :)

0

A jak zrobic w takim przypadku?

 
template<typename T>
class Test
{
public:
    static T zmienna;
};
1

Tak samo:

#include <iostream>
 
using namespace std;
 
template<typename T>
class Test {
public:
  static T zmienna;
};
 
template <typename T>
T Test<T>::zmienna = 10;
 
template<>
double Test<double>::zmienna = 10.5;
 
int main() {
  cout << Test<int>::zmienna << '\n';
  cout << Test<double>::zmienna << '\n';
        
  return 0;
}

http://ideone.com/E5YH1

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