C++ - 为什么这个成员需要声明为静态的?

发布于 2024-10-11 06:49:16 字数 927 浏览 4 评论 0原文

这让我发疯。我收到“没有对 '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;

And that generated。

不过,我真的不知道为什么,这还不够好:)如果有人可以解释这里发生的事情,我将非常感激。顺便说一下,我正在使用 libCinder (libcinder.org)

This was driving me insane. I was getting a "No matching function call to 'WordCloud::WordCloud()'" error. It seems that a default constructor was being called, but because I didn't define one, the error was being thrown.

The constructor is:

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

And in the main cpp file, the error was occurring on the indicated line

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
};

So, I'm guessing a WordCloud object was being instantiated when the FontTestingApp class was instantiated.

If I comment out the line

WordCloud wc;

Then it compiles.

To fix it I finally changed the line to

static WordCloud wc;

And that compiled.

I really don't know why, though, and that's not good enough :) If someone could explain what's going on here I'd be very grateful. I'm using libCinder by the way (libcinder.org)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

抱着落日 2024-10-18 06:49:16

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

解决方案是在 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);

请注意,如果您根本不实例化该变量,那么当您尝试在其他地方引用它时,您当然会收到链接器错误。

Non-static member variables in a class are instantiated (ie, their constructors are called) when the containing object is constructed. By default, the zero-argument default constructor is called - but the compiler only provides this for you if you do not provide any explicit constructors.

The solution is to explicitly construct the wc object in the FontTestingApp constructor:

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

As for why the static change suppressed the error, the declaration static WordCloud wc; in the class definition does not instantiate the object; it merely declares it, in exactly the same way that an extern WordCloud wc; at file scope would not instantiate the class. Indeed, static member variables are essentially the same as extern globals, except that their name and access control rules are based on the class they are in.

Had you actually instantiated the static member variable in some .cpp file with:

WordCloud FontTestingApp::wc;

Then you would have got an error. Of course, you could pass in constructor parameters to resolve this:

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

Note that if you don't instantiate the variable at all, you will of course get a linker error if you attempt to reference it elsewhere.

安静 2024-10-18 06:49:16

您对编译器为何寻找默认构造函数的猜测是正确的;您没有在 FontTestingApp 构造函数的初始值设定项列表中显式调用相关的 WordCloud 构造函数。

至于为什么static方法“有效”;事实并非如此。静态成员声明还必须附有定义(通常类似于 CPP 文件中某处的 WordCloud FontTestingApp::wc(/*args*/); 的行。没有它,就不会实例化任何对象,因此不会调用构造函数。

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

Your guess about why the compiler was looking for the default constructor is correct; you don't explicitly call the relevant WordCloud constructor in an initializer list in a FontTestingApp constructor.

As for why the static approach "works"; it doesn't. Static member declarations must also be accompanied by definitions (typically along the lines of WordCloud FontTestingApp::wc(/*args*/); in a CPP file somewhere. Without out that, no object is instantiated, and hence no constructor is called.

Note: as I'm sure you're aware, the semantics of a static class member are very different to those of a non-static member.

南风起 2024-10-18 06:49:16

由于您提供了自定义构造函数(对于 WordCloud),编译器不再生成默认构造函数。

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

Because you have provided the custom constructor (for WordCloud), the compiler no longer generates the default ctor.

If WordCloud is not your class, then you have ensure that in all your constructors (including a default one for class FontTestingApp) you construct the member correctly in the initializer list.

锦爱 2024-10-18 06:49:16

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

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

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

If you declare constructor with parameters and wanna use constructor without parameters you must declare the last explicitly. But you don't use wc constructor with parameters. If you wanna do this, you must write something like this:

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

Using "static" statement is only declaration of data member but not definition. That's why your code compiled without errors.

把回忆走一遍 2024-10-18 06:49:16

如果您使用非默认构造函数,则必须定义一个默认构造函数。当成员是静态的时,除非您显式定义它(而不是声明它),否则不会为其分配内存,这可能就是您没有收到错误的原因。

You have to define a default constructor if you are using a non-default one. When the member is static, no memory is allocated for it until you explicitly define it (as opposed to declaring it), that's probably why you didn't get the error.

子栖 2024-10-18 06:49:16

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

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

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

The problem, I'm guessing, is that the WordCloud class doesn't have a default constructor. Consequently, if the compiler auto generates a default constructor for FontTestingApp, it will try to call a nonexistent constructor for the WordCloud data member, hence the compiler error.

Marking the WordCloud member static masks but does not fix this problem because static data members are not initialized in constrictors. That's why your code was able to compile with the modification.

To fix this problem, provide a constructor for your FontTestingApp class that uses the member initialization list to call an appropriate constructor for the WordCloud data member.

锦欢 2024-10-18 06:49:16

您不得将 wc 成员设置为静态。

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

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

You must not make the wc member static.

You must instead call the constructor for your class explicitely from the FontTestingApp constructor's initialization list, like this:

FontTestingApp::FontTestingApp(): wc(&wordList) {
    // more initialization
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文