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 编译)为此代码生成两个我认为相关的错误(尽管我不明白如何......)

错误 1

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

我在 stackoverflow 上的搜索是在引用基类时需要命名空间,其中提到注入的类名作为进一步搜索的起点。但是,根据我收集到的信息,这解释了为什么我可以A按照我的方式编写构造函数(即 as A(int i=42):BarInt(i){};)以及为什么BarInt(i)不必使用 namespace 来限定N

那么为什么这不起作用B呢?根据 C++11 中的'typedef'和'using'有什么区别?,using与 good old 相同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.0。

后经

因为这是我在这里的第一篇文章:您好 stackoverflow,感谢大家通过帮助他人解决问题为我提供的巨大帮助!

4

1 回答 1

1

从类继承时,派生类可以无条件地访问基类的名称(包括基类名称本身)。您实际上是在继承基类中的名称。这就是为什么继承自允许您无条件N::BarInt地引用BarInt内部。A

对于B,您从Foo<double>使用 BarFloat 别名继承,但Foo<double>不包含BarFloat,因此您不会继承该名称。

第二个错误只是因为第一个失败。由于编译器没有看到基础的有效初始化,就像您根本没有显式初始化基础一样,因此它被迫使用您没有的默认构造函数对其进行初始化。

于 2013-01-16T16:50:44.097 回答