2016-03-25 9 views
0

Betrachten Sie die folgenden Header-Dateien.Wie generiert der Compiler Vorlagenklassendefinitionen?

In meinen Object.h

#ifndef OBJECT_H_ 
#define OBJECT_H_ 

#include <iostream> 

template <class Policy> 
class Object 
{ 
    friend Policy; 
private: 
    Policy* p; 
    int hash; 

public: 
Object():p(new Policy(this)),hash(0){} 
    ~Object(){delete p;} 

    void set(){p->setHash();} 

    void show() const{std::cout<<"hash = "<<hash<<std::endl;} 
}; 

#endif // OBJECT_H_ 

Dann habe ich zwei Richtlinien, P1 und P2 mit unterschiedlichen Hash-Werten.

In p1.h

#ifndef P1_H_ 
#define P1_H_ 

template <class Policy> class Object; 

class P1 
{ 
    enum {p1 = 1}; 
    Object<P1>* t; 

public: 
    P1(Object<P1>* at):t(at){} 
    void setHash(){t->hash = p1;} 
}; 

#endif // P1_H_ 

In p2.h

#ifndef P2_H_ 
#define P2_H_ 

template <class Policy> class Object; 
class P2 
{ 
enum {p2 = 2}; 

Object<P2>* t; 

public: 
P2(Object<P2>* at):t(at){} 
//void setHash(){t->hash = p2;} // ** Notice here ** 
}; 
#endif // P2_H_ 

In meinem main.cpp Ich habe

#include "Object.h" 
#include "p1.h" 
#include "p2.h" 

int main() 
{ 
    Object<P1> t1; 
    t1.set(); 
    t1.show(); 

    Object<P2> t2; 
    //t2.set(); 
    t2.show(); 
} 

Ergebnis auf OS X:

hash = 1

hash = 0

Beobachtungen:

  1. Es kompiliert und ordnungsgemäß ausgeführt. Beachten Sie, dass die Definition von Object<P2> nicht vollständig ist. Da P2 nicht setHash() definiert hat.

  2. Wenn ich den Kommentar in meinem Haupt loswerden, wird es einen Fehler melden.

    ./Object.h:20:8: Fehler: Kein Mitglied namens 'setHash' in

    main.cpp 'P2': 12: 6: Anmerkung: in Instanziierung Elementfunktion ‚Objekt :: set 'angefragt hier t2.set();

Fragen

  1. das Objektelement innerhalb P1 oder P2-Klasse halten würde für jeden von ihnen sogar Klassendefinition Compiler generieren, wenn ich in Haupt keine Instanz von Object<P1> oder Object<P2 erstellen?

  2. Warum Object<P2> ist OK? Da die Definition unvollständig ist.

+0

"dann wird es einen Fehler melden" Was ist? – user657267

+0

@ user657267 oben hinzugefügt. – Ling

Antwort

1

Consider the Object member inside P1 or P2 class would compiler generate class definition for each of them even if I do not create an instance of Object<P1> or Object<P2> in main?

No. Die Mitglieder sind Object<P1>* t; und Object<P1>* t; - sie sind nicht static sind so nur erstellt, wenn P1 und P2 Objektinstanzen erstellt werden, und sie sind Zeiger so dass selbst dann kein Object<P1>* erstellt: der Zeiger übergeben an den Konstruktor - der nullptr/0 sein kann - wird einfach gespeichert.

Why Object is OK? Since the definition is incomplete.

Mit Vorlagen werden Funktionen nur instanziiert, wenn sie aufgerufen werden. Solange sie richtig geparst werden können, ist es kein Fehler.

+0

Danke. Ich sehe jetzt. – Ling

1

Es sind keine Object<P1> oder Object<P2> Mitglieder innerhalb P1 und P2. Es gibt Object<P1>* und Object<P2>* Mitglieder. Ein Zeiger auf einen unvollständigen Typ ist vollkommen in Ordnung. Der Typ selbst wird nicht instanziiert, es sei denn, der Zeiger wird dereferenziert.

In Ihrer main-Funktion ist Object<P2> ein vollständiger Typ, aber seine nicht virtuellen Memberfunktionen werden immer noch nicht instanziiert, es sei denn, sie werden aufgerufen (oder besser gesagt, ODR-verwendet). Aus diesem Grund ist es in Ordnung, Object<P2> t2; zu haben, aber das Aufrufen von t2.set() ist ein Fehler.

+0

Danke an Sie und Tony D. – Ling

Verwandte Themen