1
template<class T>
Queue<T>::Queue(): frontPtr(NULL), backPtr(NULL), count(0)
{
}

Queue():だけではないのはなぜQueue()ですか?

4

3 に答える 3

4

他の人がコメントしたように、:は初期化子リストの存在を示します。詳細については、お気に入りの C++ の本また​​は多数の優れた Web サイトを参照してください。簡単な Google 検索で、よく書かれていると思われるこの記事が表示されました: http://www.cprogramming.com/tutorial/initialization-lists-c++.html

初期化子リストの短いエグゼクティブ サマリーが必要な場合は、次のようにします。初期化子リストには、基本クラス コンストラクターへの呼び出しと、メンバー変数のコンストラクターへの呼び出しを含めることができます。

どうしてそんなものを欲しがるの?まあ、多くの理由。


コードはかなり単純化されており、少しばかげた部分 (Nameクラスなど) が含まれていることに注意してください。目的は、イニシャライザ リストがどのように機能するかを示すことであり、派手なコードを記述したり、考えられるすべての C++ 機能を活用したりすることではありません。


基底クラスの構築

構築するためにいくつかのパラメーターを必要とする基本クラスがあるとします。コンストラクターに必要なパラメーターを渡す方法は他にありません。これは、{コンストラクターの本体を開く が "実行" するまでに (このコンテキストでの "実行" の使用がやや緩いことを許してください)、基底クラスが既に構築されているためです。 :

class Name
{
    const char *name;

public:
    Base(const char *n)
    {
        name = n;
    }

    const char *getName() const
    {
        return name;
    }
};

class Derived : public Name
{
    int a;

public:
    Derived(int x)
        : Name("Derived")
    {
        a = y;
    }

    // Without the call to Name("Derived") in the constructor initializer
    // list how could you possibly initialize the base class here?
};

クラス インスタンスであるメンバーの構築

同様に、引数を必要とするコンストラクターを持つクラス メンバーがあるとします。問題は似ています: 引数を渡すためにこれらのコンストラクターをどこで呼び出し、どのように渡すことができるでしょうか? 答えは初期化リストにあります。前の例を拡張してみましょう。

class Name
{
    const char *name;

public:
    Base(const char *n)
    {
        name = n;
    }

    const char *getName() const
    {
        return name;
    }
};

class MyInt
{
    int value;

public:
    MyInt(int i)
    {
        value = i;
    }

    int getInt() const
    {
        return value;
    }
}

class Derived : public Name
{
    MyInt a;

public:
    Derived(int x)
        : Name("Derived"), a(x)
    {

    }

    // Without the call to a(x)  in the constructor initializer
    // list how could you possibly initialize that member variable 
    // here?
};

メンバー変数を効率的に初期化する

代入の左側に手動で値を変数に設定する場合、実際にはそれを「初期化」していません。代わりに課題を実行しています。

これはやや難解な違いかもしれませんが、多くの重要な意味があります。その 1 つ (そして最も重要なものでさえありません) は、パフォーマンスです。

C では、すべての基底クラスとすべてのメンバー変数のコンストラクターが、コンストラクター本体の実行を開始する前に完了する必要があるため、これは、これらのコンストラクターの 1 つでかなりの量の作業が行われることを意味する場合があります。これらのメンバー変数の 1 つに新しい値を割り当てると、すべての作業が失われる可能性があります。

そのため、必要な値をコンストラクター初期化子リストに渡すことで、(型に関係なく) メンバー変数を初期化できます。最後の例を作り直してみましょう:

class Name
{
    const char *name;

public:
    Base(const char *n)
        : name(n)
    {
        // notice that at this point the member variable "name"
        // has already been initialized and can be accessed. 
    }

    const char *getName() const
    {
        return name;
    }
};

class MyInt
{
    int value;

public:
    MyInt(int i)
        : value(i)
    {
        // Again, note here that the variable "value" already contains
        // its value. We need not initialize it again.
    }

    int getInt() const
    {
        return value;
    }
}

class Derived : public Name
{
    MyInt a;

public:
    Derived(int x)
        : Name("Derived"), a(x)
    {

    }
};

物事の初期化を少し動かした方法を観察してください。私たちのプログラムは同じように動作しますが、動作が大きく異なります。理由を確認するために、別のクラスをミックスに追加してみましょう。

class Name
{
    const char *name;

public:
    Base(const char *n)
        : name(n)
    {
        // notice that at this point the member variable "name"
        // has already been initialized and can be accessed. 
    }

    const char *getName() const
    {
        return name;
    }
};

class MyInt
{
    int value;

public:
    MyInt(int i)
        : value(i)
    {
        // Again, note here that the variable "value" already contains
        // its value. We need not initialize it again.
    }

    int getInt() const
    {
        return value;
    }
}

class Example : public MyInt
{
    const char *type;

public:
    Example()
        : MyInt(0), type("default")
    {
    }

    Example(int x)
        : MyInt(x), type("custom")
    {
    }

    const char *getType() const
    {
        return type;
    }
}

class Derived : public Name
{
    Example a;
    Example b;

public:
    Derived(int x)
        : Name("Derived"), a(x)
    {

    }

    void print()
    {
        std::cout << "This is an " << getName() << " instance" << std::endl;
        std::cout << "  a has a " << a.getType() << " value" << std::endl;
        std::cout << "    a=" << a.getInt() << std::endl;
        std::cout << "  b has a " << b.getType() << " value" << std::endl;
        std::cout << "    b=" << b.getInt() << std::endl;
    }
};

int main(int argc, char **argv)
{
    Derived d;

    d.print(123);

    return 0;
}
于 2013-10-30T01:41:24.237 に答える
3

コロンは、initializer listコンストラクターの を示します。
これにより、クラスのメンバー変数を値で初期化できます。

以下はほぼ同じです (ただし、より効率的ではありませんInitializer List)。

template<class T>
Queue<T>::Queue()
{
 frontPtr = NULL;
 backPtr = NULL;
 count = 0;
}
于 2013-10-30T01:05:39.570 に答える
-3

これ:

template<class T>
Queue<T>::Queue(): frontPtr(NULL), backPtr(NULL), count(0)
{
}

以下とほぼ同じ目的を達成します。

template<class T>
Queue<T>::Queue()
{
    frontPtr = NULL;
    backPtr = NULL;
    count = 0;
}

次のようないくつかの重要な違いがあります。

  • 初期化子リストを使用すると、構築と初期化を 2 つの別個の操作として行うことはありません。
  • const初期化子リストを使用することが、メンバー変数を初期化できる唯一の方法です。
于 2013-10-30T01:10:11.250 に答える