【问题标题】:g++ mistakes base constructor for field and ignores parameters to itg ++错误的字段的基本构造函数并忽略它的参数
【发布时间】:2016-03-26 04:41:34
【问题描述】:

我有一个基类 class A<T> 和一个派生类 class B : public A<string>

class A 有一个以整数作为唯一参数的构造函数和一个标准的复制构造函数。它没有无参数的默认构造函数(不是我定义的;我意识到编译器可能正在创建一个,这可能与我的问题有关)。

class B 的构造函数如下所示:

B()
: A(37)
{

}

我得到的错误是:

编译器将基构造函数调用错误地初始化为字段

fileB.h: In constructor ‘B::B()’:
fileB.h:25: error: class ‘B’ does not have any field named ‘A’

编译器认为正在使用默认(无参数)基类构造函数,并建议使用两个非默认基类构造函数...

// Where is it getting this? A() is never written explicitly
fileB.h:25: error: no matching function for call to ‘A<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::A()’
fileA.h:37: note: candidates are: A<T>::A(const A<T>&) [with T = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]

...其中一个应该与被调用的内容匹配。

// This one matches A(37), right?
fileA.h:24: note:                 A<T>::A(const int&) [with T = std::basic_string<char, std::char_traits<char>, std::allocator<char> >]

我相信这个错误来自我的编译器的安装或配置方式,因为当我在我的计算机上编译我的代码时,我没有收到任何错误,但是当我将所有内容 scp 到我的学校的电脑并在那里编译。我在这两个地方都使用了 g++,但显然某处存在一些差异。有什么区别,错误来自哪里?

不存在从 A 到 int 的转换运算符,反之亦然。

我在两个系统上都使用 c++03。

这是重现错误的完整代码示例(同样,仅在一个系统上):

/*******************************
 * fileA.h
 ******************************/

template <class T>
class A
{
   int member;

  public:

   A(const int & m)
      : member(m)
   {
   }

   A(const A & copyFrom)
   {
      member = copyFrom.member;
   }
};


/*******************************
 * fileB.h
 ******************************/

#include <string>
#include "fileA.h"

using namespace std;

class B : public A<string>
{   
   B()
      : A(37)
   {

   }   
};

【问题讨论】:

  • 我在哪里做的?
  • class B : public class A&lt;string&gt; - 它真的是这样编译的吗,在A&lt;string&gt;之前加上class这个词?
  • Grr。不,抱歉,这只是class B : public A&lt;string&gt;。我现在就编辑它。
  • 提供具有可重现错误的可编译代码示例可能是有意义的。看起来 GCC 应该按原样编译您的构造函数(即我的原始答案不正确)。

标签: c++ templates inheritance compiler-errors g++


【解决方案1】:

首先,编译器不会生成 A 的默认构造函数。如果至少定义了一个带参数的构造函数,则不会生成默认构造函数。

其次,您的问题来自您没有在 B 构造函数中指定 A 的模板参数这一事实。你必须写:

B() : A<string>(37) {}

当您编写 A(37) 时,编译器会查找不存在的非模板类 A。

基类总是被构造的。由于您不构造 A ,编译器将为您调用默认构造函数。因为它不存在所以失败。

【讨论】:

  • 使用A(37) 代替A&lt;string&gt;(37) 在一个使用g++ 的系统上完美运行,但在另一个使用g++ 的系统上却不行。我知道A&lt;string&gt; 是一个更明确的类型说明符,但为什么只需要在一个系统上?
  • 这应该行不通。但它肯定是实现定义的。您的一个实现可能会猜测您的意思是 B 构造函数中的 A 因为您在类声明中从 A 派生了 B。
  • 你是什么意思“实现定义”? g++就是g++,不是吗?
  • 或许您可以详细介绍一下这两个系统以及正在使用的 g++ 的版本?
  • 我在考虑不同的版本。你可以给我们更多的信息。你说的是什么系统。尤其是您的编译器的版本是什么。帮助你会更容易。
猜你喜欢
  • 2017-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
  • 2012-04-18
  • 1970-01-01
  • 2011-10-08
相关资源
最近更新 更多