2013-07-08 25 views
7

Nel seguente programma "Qui" è stampata:variabili statiche C++ della classe senza riferimenti

#include <iostream> 
class Base 
{ 
    static bool temp; 
    static bool initTemp() 
    {std::cout<<"Here\n";return true;} 
}; 

bool Base::temp = Base::initTemp(); 

class Derived : public Base 
{}; 

int main() {int a;std::cin>>a;} 

Nel seguente programma "Qui" non viene stampata:

#include <iostream> 
template <class T> 
class Base 
{ 
    static bool temp; 
    static bool initTemp() 
    {std::cout<<"Here\n";return true;} 
}; 

template <class T> 
bool Base<T>::temp = Base<T>::initTemp(); 

class Derived : public Base<int> 
{}; 

int main() {int a;std::cin>>a;} 

In entrambi i casi Base non è mai riferimento. L'unica differenza è che nel secondo caso è una classe template. Qualcuno può spiegarmi perché questo comportamento si verifica. Sto usando VS 2012.

+2

'void main()' non è legale C++. Dovrebbe essere 'int main()'. –

+0

Nel secondo esempio, "Qui" viene stampato se si crea un'istanza esplicita del membro statico: 'modello bool Base :: temp;' – willj

risposta

6

In entrambi i casi Base non viene mai referenziato.

E questo è esattamente il motivo per cui non si vede nulla di essere stampato sullo standard output.

La definizione del membro di dati statici di un modello di classe non viene creata un'istanza a meno che non si utilizzi tale membro dati; come le funzioni membro, le definizioni dei membri di dati statici di un modello di classe vengono istanziate su richiesta.

Questo è specificato al paragrafo 14.7.1/1 della C++ 11 standard:

[...] L'istanziazione implicita di una specializzazione template di classe fa sì che l'implicita esemplificazione delle dichiarazioni, ma non delle definizioni o degli argomenti predefiniti, delle funzioni membro classe, classi membro , elenchi membri con ambito, membri dati statici e modelli membri. [...]

Dal momento che il codice del client non si riferisce a Base<>::temp, non c'è bisogno di costruire e inizializzarlo.


Come nota a margine, questa firma:

void main() 

non è valido (standard) C++. Se si desidera scrivere codice portatile, il tipo di reso di main() deve sempre essere int.

+0

Ma il codice contiene 'classe Derivato: Base ' ... (perché) non conta come istanziazione? –

+0

Ho modificato il post in modo che utilizzi int. Esiste un modo per creare un'istanza della classe ereditandola? cioè c'è un modo per inizializzare automaticamente temp per molti diversi tipi derivati ​​senza dover scrivere il modello <> bool Base :: temp = Base :: initTemp(); –

+0

@KonradRudolph: "* L'istanza implicita di una specializzazione del modello di classe causa l'istanza implicita delle dichiarazioni, ma non delle definizioni o degli argomenti predefiniti, delle funzioni membro classe, classi membro , enumerazioni membro con ambito, membri dati statici e modelli di membri * "(14.7.1/1) –

-3

Non è possibile creare variabili di classe indefinita, che ti sembra di fare con la linea:

template <class T> 
bool Base<T>::temp = Base<T>::initTemp(); 

Non si può allocare variabile di tipo non definito. Quello che vi serve è scrivere qualcosa di simile:

Base<int>::temp = value; 

di causa ci saranno diverse variabili assegnato per ogni tipo di condizione, quindi non si può avere variabile statica comune per una classe template. Avrai invece una variabile separata per ciascun tipo per istanziare il tuo modello.

Per downvoters qui è completo esempio:

#include <iostream> 

template<class T> 
class X 
{ 
public: 
    static int v; 
}; 

template<class T> 
int X<T>::v = 0; 

int main() 
{ 
    X<int>::v = 3; 
    X<char>::v = 2; 

    using namespace std; 
    cout << X<char>::v << endl << X<int>::v; 
} 

esso stampa 2 3 che significa che non si può avere un'unica variabile per tutte le classi si istanzia il modello.

+1

È assolutamente possibile. –

+0

Penso che cosa intendesse Bogolt è che per ogni istanstiation di X avrai un valore diverso di v. Questo è vero ma voglio avere un valore diverso di v per ogni istanza. Per condividere la stessa variabile statica tra tutte le istanze X deve ereditare da una classe base non modello che contiene v. –

+0

L'esempio di codice mostra in realtà che * puoi * fare esattamente ciò che ritieni di non poter fare. –

2

Nel primo caso, non è un'istanza Base, ma si fa chiamare la funzione statica:

bool Base::temp = Base::initTemp(); 

Nel secondo caso, non si crea un'istanza della template:

template <class T> 
bool Base<T>::temp = Base<T>::initTemp(); 

È può istanziare esplicitamente il modello Base classe, come con:

template class Base<int>; 

E poi vedrai "Qui" stampato.

+0

OK, è bello, non sapevo che in avanti dichiarare una classe template lo istanziasse. –

+1

@BenjyKessler: Questa non è una dichiarazione anticipata, è un'istanza esplicita –

+0

@BenjyKessler: lol, sì, ha modificato il commento. Il mio cervello sta dormendo –

Problemi correlati