C ++ - 为什么这个成员需要声明为static?

时间:2011-01-12 09:09:16

标签: c++ static-members

这让我疯了。我得到一个“没有匹配函数调用'WordCloud :: WordCloud()'”错误。似乎正在调用默认构造函数,但由于我没有定义一个,因此抛出了错误。

构造函数是:

WordCloud( map<string, int> *source ); 

在主cpp文件中,错误发生在指示的行

class FontTestingApp : public AppBasic 
{                                      // <-- error was appearing on this line
public:
  void setup();
  void mouseDown( MouseEvent event ); 
  void update();
  void draw();

  map<string, int> wordList;
  WordCloud wc;        // comment out this line and it compiles
};

所以,我猜测在实例化FontTestingApp类时实例化了一个WordCloud对象。

如果我注释掉该行

WordCloud wc;

然后编译。

为了解决这个问题,我终于将线路改为

static WordCloud wc;

并编译。

我真的不知道为什么,而且这还不够好:)如果有人能解释这里发生了什么,我会非常感激。我顺便使用了libCinder(libcinder.org

7 个答案:

答案 0 :(得分:5)

在构造包含对象时,实例化类中的非静态成员变量(即,调用它们的构造函数)。默认情况下,调用零参数默认构造函数 - 但是如果您不提供任何显式构造函数,编译器只会为您提供此函数。

解决方案是在FontTestingApp构造函数中显式构造wc对象:

FontTestingApp::FontTestingApp()
    : wc(&wordList)
{ /* ... */ }

至于static更改抑制错误的原因,类定义中的声明static WordCloud wc;不会实例化该对象;它只是声明它,与文件范围的extern WordCloud wc;不会实例化类的方式完全相同。实际上,静态成员变量与extern全局变量基本相同,只是它们的名称和访问控制规则基于它们所在的类。

您是否实际在以下.cpp文件中实例化了静态成员变量:

WordCloud FontTestingApp::wc;

然后你就会出错。当然,您可以传递构造函数参数来解决此问题:

static map<string, int> dummy_word_source;
WordCloud FontTestingApp::wc(&dummy_word_source);

请注意,如果您根本没有实例化变量,那么如果您尝试在别处引用它,您当然会收到链接器错误。

答案 1 :(得分:1)

因为您提供了自定义构造函数(对于WordCloud),所以编译器不再生成默认的ctor。

如果WordCloud不是您的类,那么您必须确保在所有构造函数中(包括类FontTestingApp的默认构造函数))在初始化列表中正确构造成员。

答案 2 :(得分:1)

您猜测编译器为什么要查找默认构造函数是正确的;您没有在WordCloud构造函数的初始化列表中显式调用相关的FontTestingApp构造函数。

至于为什么static方法“有效”;它没有。静态成员声明还必须附带定义(通常沿着CPP文件中的WordCloud FontTestingApp::wc(/*args*/);行。除此之外,没有对象被实例化,因此不会调用构造函数。

注意:我确信你知道,静态类成员的语义非常与非静态成员的语义不同。

答案 3 :(得分:1)

如果使用参数声明构造函数并想使用不带参数的构造函数,则必须显式声明最后一个。但是你不要将wc构造函数与参数一起使用。如果你想这样做,你必须写下这样的东西:

class FontTestingApp : public AppBasic 
{                                 
    public:
...
    FontTestingApp() : wc(&wordList) {}
    map<string, int> wordList;
    WordCloud wc;      
};

使用“static”语句只是数据成员的声明,而不是定义。这就是为什么你的代码编译没有错误。

答案 4 :(得分:0)

如果使用的是非默认构造函数,则必须定义默认构造函数。当成员是静态的时,在你明确定义它之前没有为它分配任何内存(而不是声明它),这可能就是你没有得到错误的原因。

答案 5 :(得分:0)

我猜,问题是WordCloud类没有默认构造函数。因此,如果编译器自动为FontTestingApp生成默认构造函数,它将尝试为WordCloud数据成员调用不存在的构造函数,因此编译器错误。

标记WordCloud成员静态掩码但不解决此问题,因为静态数据成员未在缩写器中初始化。这就是为什么你的代码能够通过修改进行编译的原因。

要解决此问题,请为FontTestingApp类提供一个构造函数,该构造函数使用成员初始化列表为WordCloud数据成员调用适当的构造函数。

答案 6 :(得分:0)

你不能让wc成员静态。

您必须从FontTestingApp构造函数的初始化列表中明确地为您的类调用构造函数,如下所示:

FontTestingApp::FontTestingApp(): wc(&wordList) {
    // more initialization
}