2

次のようなクラスを考えてみましょう:

template < class T >
class MyClass
{
  private:
    static T staticObject;
    static T * staticPointerObject;
};
...
template < class T >
T MyClass<T>::staticObject; // <-- works
...
template < class T >
T * MyClass<T>::staticPointerObject = NULL; // <-- cannot find symbol staticPointerObject.

そのポインター オブジェクトを正常に作成できない理由がわかりません。

上記のコードはすべてヘッダーで指定されており、私が言及した問題はリンク手順のエラーであるため、特定のシンボルが見つかりません。

4

5 に答える 5

2

「シンボル staticPointerObject が見つかりません」 - これはリンカーエラー メッセージのように見えます。それは...ですか?(このような詳細は、質問で指定する必要があります)。

そうである場合、静的メンバーの定義を実装ファイル (.cpp ファイル)に入れているために発生する可能性が最も高いです。これが正しく機能するためには、定義をヘッダー ファイル (.h ファイル) に配置する必要があります。

繰り返しますが、このような詳細は質問で指定する必要があります。それらがなければ、それはランダムな推測フェストに変わります.

于 2010-08-04T18:19:22.677 に答える
1

最初の例が次の理由であると思われます(2003 C++ std ドキュメントから)。特に最後の文に注意してください-あなたの例から、「メンバー定義が存在することを必要とする」ものは何もないようです。

14.7.1 暗黙のインスタンス化 [temp.inst] 1 クラス テンプレートの特殊化が明示的にインスタンス化 (14.7.2) または明示的に特殊化 (14.7.3) されていない限り、クラス テンプレートの特殊化は、特殊化がコンテキスト内で参照されるときに暗黙的にインスタンス化されます。完全に定義されたオブジェクト型が必要な場合、またはクラス型の完全性がプログラムのセマンティクスに影響する場合。クラス テンプレートの特殊化の暗黙的なインスタンス化により、宣言の暗黙的なインスタンス化が発生しますが、クラス メンバー関数、メンバー クラス、静的データ メンバー、およびメンバー テンプレートの定義または既定の引数のインスタンス化は発生しません。そして、メンバーの匿名共用体の定義の暗黙的なインスタンス化を引き起こします。クラス テンプレートまたはメンバー テンプレートのメンバーが明示的にインスタンス化または明示的に特殊化されていない限り、メンバー定義が存在する必要があるコンテキストで特殊化が参照されると、メンバーの特殊化は暗黙的にインスタンス化されます。特に、静的データ メンバーの定義が存在する必要がある方法で静的データ メンバー自体が使用されない限り、静的データ メンバーの初期化 (および関連する副作用) は発生しません。

于 2011-12-31T03:18:33.733 に答える
0

静的メンバーの最初の「定義」は単なる宣言です。これが標準からの引用です。

15宣言に初期化子が含まれている場合、テンプレートの静的データメンバーの明示的な特殊化は定義です。それ以外の場合は、宣言です。[注:デフォルトの初期化を必要とするテンプレートの静的データメンバーを定義するための構文はありません。template <> X Q :: x; これは、Xをデフォルトで初期化できるかどうか(8.5)に関係なく宣言です。]

2番目の定義は機能するはずです。1つのコンパイルユニットですべてを利用できますか?エラーメッセージの正確なテキストは何ですか?

以下はg++でコンパイル/実行します-すべて1つのファイルに

#include <iostream>

template < class T >
class MyClass
{
  public:
    static T staticObject;
    static T * staticPointerObject;
};

template < class T >
T MyClass<T>::staticObject;

template < class T >
T * MyClass<T>::staticPointerObject = 0; 

int main(int argc, char **argv)
{
  int an_int = 5;
  MyClass<int>::staticPointerObject = &an_int;
  std::cout << *MyClass<int>::staticPointerObject << std::endl;

  char a_char = 'a';
  MyClass<char>::staticPointerObject = &a_char;
  std::cout << *MyClass<char>::staticPointerObject << std::endl;
}
于 2010-08-04T18:59:33.560 に答える
0

私はいつも次のトリックを使用します。アイデアは、静的を関数に入れ、その関数からのみアクセスすることです。このアプローチにより、ファイル内で static を宣言する必要がなくなります。.cppすべてがファイル内に存在でき.hます。サンプルコードに従ってください:

template < class T >
class MyClass
{
  public:
    static T * getObject() {
      // Initialization goes here.
      static T * object = NULL; // or whatever you want
      return pointerObject;
    }
};
于 2011-02-19T23:38:57.500 に答える
0

私は2つの解決策を見つけました。どちらも私が望んでいた100%ではありません。

  1. 特定のインスタンスを明示的に初期化します。

    int * MyClass<int>::staticPointerObject = NULL;

これは、特に私がたくさんの異なるタイプを持っている場合には便利ではありません.

  1. クラス内でポインターをラップします。

    template < class T >   
    class MyClass   
    {   
      private:   
        struct PointerWrapper   
        {   
          T * pointer;   
          PointerWrapper( void )   
            : pointer( NULL )   
          { }   
        };   
        T staticObject;   
        PointerWrapper staticPointerObject;   
    };   
    ...   
    template < class T >   
    T MyClass<T>::staticObject; // <-- works fine.   
    ...   
    template < class T >   
    MyClass<T>::PointerWrapper MyClass<T>::staticPointerObject; // <-- works fine.

これは少し面倒ですが、少なくとも使用可能です。変数オブジェクトをインスタンス化できるのに、変数オブジェクトへのポインターをインスタンス化できないのはなぜですか? 逆に問題が増えると思います(コンパイラは、ポインターがどのように見えるかを事前に知っていますが、オブジェクトがどのように見えるかは知りません)。

誰かがより良い答えを持っているなら、私はそれを見たいです!

于 2010-08-04T18:38:30.730 に答える