在另一个名称空间中调用别名声明的基类构造函数

时间:2013-01-16 16:42:57

标签: c++ c++11 constructor base-class using-declaration

我试图通过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的搜索提出了Is a namespace required when referring to the base class,它提到了注入的类名作为进一步搜索的起点。但是,根据我收集的内容,这解释了为什么我可以像A那样编写A(int i=42):BarInt(i){};的构造函数(即BarInt(i))以及为什么N不必使用名称空间B

那为什么不能与using一起使用?根据{{​​3}},typedef与旧的BarFloat相同,所以我想我的第一个错误的问题是如何在我的示例中声明了alias声明的类(BarInt )在注入类名的上下文中,与常规类(在我的示例中为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 )不同。非常感谢任何指针:)

错误2

Foo()

如果我(如上面的示例代码中已经提到的那样)引入了一个空BarFloat(f)构造函数,则此错误消失了。但是,我的问题是Foo()触发对空BarFloat.value构造函数的调用的原因,在这种情况下,{{1}}如何设置为23.0。

Post Scriptum

这是我在这里发表的第一篇文章:Hello stackover流程,感谢大家通过帮助他人解决问题所提供的巨大帮助!

1 个答案:

答案 0 :(得分:0)

从类继承时,派生类可以无限制地访问基类的名称(包括基类名称本身)。您实际上是在基类中继承名称。这就是继承N::BarInt的原因,您可以在BarInt内无需资格参考A

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

第二个错误只是因为第一次失败。由于编译器没有看到基类的有效初始化,它就像你根本没有明确地初始化基类一样,所以它被强制用你没有的默认构造函数初始化它。