1

私は、C ++ 11を介してエイリアス宣言されたクラスの詳細とusing、これが基本クラスのコンストラクター呼び出しにどのように/なぜ影響するのかを理解しようとしています。

サンプルコード

#include <iostream>

namespace N {

  template<typename T>
  struct Foo
  {
//     Foo(){}; // NOTE: If this line is present, error 2 goes away.
    Foo(T t):value(t){};
    ~Foo() = default;
    T value; 
  };

  struct BarInt : public Foo<int>
  {
    BarInt(int t):Foo< int >(t){};
    ~BarInt() = default;
  };

  using BarFloat = Foo<float>;

};

struct A : public N::BarInt
{
  A(int i=42):BarInt(i){}; //BarInt(i) or N::BarInt(i) doesn't matter here
  ~A() = default;
};

struct B : public N::BarFloat
{
  B(float f=23.0):BarFloat(f){}; //two errors with gcc4.7.2 (with -std=gnu++11)

//   B(float f=23.1):N::BarFloat(f){}; //this line seems to work.
  ~B() = default;
};


int main(int argc, char **argv)
{
  A a;
  B b;  
  std::cout << "a's value is "<< a.value << "\n"
            << "b's value is "<< b.value << std::endl;
  return 0;
}

gcc 4.7.2(-std = gnu ++ 11でコンパイル)は、このコードに対して2つのエラーを生成します。これは、関連していると思います(ただし、方法はわかりません...)

エラー1

main.cpp: In constructor ‘B::B(float)’:
main.cpp:32:19: error: class ‘B’ does not have any field named ‘BarFloat’

私が提起したstackoverflowの検索では、基本クラスを参照するときに名前空間が必要です。これは、さらに検索するための開始点として、挿入されたクラス名に言及しています。しかし、私が集めたものから、これはA私がそれをした方法で(つまりとしてA(int i=42):BarInt(i){};)コンストラクターを書くことができる理由BarInt(i)と、名前空間で修飾する必要がない理由を説明していますN

では、なぜそれがうまくいかないのBですか?C ++ 11の「typedef」と「using」の違いは何ですか? はusing古き良きものと同じなtypedefので、最初のエラーに対する私の質問は、クラス名を挿入するコンテキストで、エイリアス宣言されたクラス(BarFloat私の例では)が通常のクラス(私の例では)とどのように異なるかということだと思います。BarIntどんなポインタでも大歓迎です:)

エラー2

main.cpp:32:29: error: no matching function for call to ‘N::Foo<double>::Foo()’
main.cpp:32:29: note: candidates are:
main.cpp:9:5: note: N::Foo<T>::Foo(T) [with T = double]
main.cpp:9:5: note:   candidate expects 1 argument, 0 provided
main.cpp:6:10: note: constexpr N::Foo<double>::Foo(const N::Foo<double>&)
main.cpp:6:10: note:   candidate expects 1 argument, 0 provided

上記のサンプルコードですでに述べたように、空のFoo()コンストラクターを導入すると、このエラーはなくなります。ただし、私が持っている質問は、なぜBarFloat(f)空のFoo()コンストラクターへの呼び出しをトリガーするのか、そしてその場合、どのようBarFloat.valueに23.0に設定されるのかということです。

ポストスクリプトム

これが私の最初の投稿です:こんにちはstackoverflowそしてあなたが彼らの問題で他の人を助けることを通してあなたがすでに私に提供してくれた途方もない助けに感謝します!

4

1 に答える 1

1

クラスから継承する場合、派生クラスは、修飾なしで基本クラスの名前(基本クラス名自体を含む)にアクセスできます。基本クラスの名前を効果的に継承しています。これが、から継承すると、資格なしで内部N::BarIntを参照できる理由です。BarIntA

の場合、 BarFloatエイリアスの使用をB継承していますが、が含まれていないため、その名前を継承しません。Foo<double>Foo<double>BarFloat

2番目のエラーは、最初の失敗が原因です。コンパイラはベースの有効な初期化を認識しなかったため、ベースを明示的に初期化していないのと同じように、ベースを持っていないデフォルトのコンストラクタで初期化する必要があります。

于 2013-01-16T16:50:44.097 に答える