2016-03-25 8 views
0

次のヘッダーファイルを検討してください。私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_ 

は、それから私は、異なるハッシュ値を持つ2つのポリシー、P1とP2を、作成しました。私main.cpp

#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_ 

p2.hp1.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_ 

私は、OS X上

#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(); 
} 

結果があります

ハッシュ= 1

ハッシュ= 0

観察

  1. これは、コンパイルし、適切に実行されます。 Object<P2>の定義が完全ではないことに注意してください。 P2はsetHash()を定義していないので。

  2. 私のメインでコメントを取り除くと、エラーが報告されます。

    ./Object.h:20:8:エラー:12:6:ノート:メンバ関数のインスタンス化の「オブジェクト::セットという名前の 'setHash' 'P2'

    main.cppにしていないメンバー'ここで要求されたt2.set();

質問

  1. 私がメインでObject<P1>またはObject<P2のインスタンスを作成しない場合でも、それらのそれぞれのクラス定義を生成するコンパイラうP1またはP2クラス内のオブジェクトのメンバーを考えてみましょうか?

  2. なぜObject<P2>が問題ありませんか?定義が不完全であるため。

+0

"エラーを報告する"どちらですか?上記に追加された – user657267

+0

@ user657267 – Ling

答えて

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?

号メンバーがObject<P1>* t;Object<P1>* t;ですコンストラクタには - nullptr/0 - 単純に格納されます。

テンプレートを使用すると、関数は呼び出されたときにのみインスタンス化されます。正しく解析できれば、間違いではありません。

+0

ありがとうございました。私は今参照してください。 – Ling

1

P1P2内部にはObject<P1>またはObject<P2>メンバーがありません。 Object<P1>*Object<P2>*のメンバーがあります。不完全な型へのポインタは完全にOKです。ポインタが逆参照されない限り、型自体はインスタンス化されません。

main関数では、Object<P2>は完全型ですが、非仮想メンバ関数は、呼び出されない限り(つまり、技術的にODRが使用されていない限り)、まだインスタンス化されません。このため、Object<P2> t2;を持っても問題ありませんが、t2.set()と呼ぶのはエラーです。ポインタが渡された:彼らはP1P2オブジェクトインスタンスが作成されるときにのみ作成されますstaticじゃない、と彼らはそうしても、その後何Object<P1>*が作成されていないポインタだ -

+0

あなたとTony D.の両方に感謝します。 – Ling

関連する問題