C++ - 为什么这个成员需要声明为静态的?
这让我发疯。我收到“没有对 '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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
类中的非静态成员变量在构造包含对象时被实例化(即调用它们的构造函数)。默认情况下,将调用零参数默认构造函数 - 但编译器仅在您不提供任何显式构造函数时才为您提供此构造函数。
解决方案是在 FontTestingApp 构造函数中显式构造
wc
对象:至于为什么
static
更改抑制了错误,声明static WordCloud wc;
在类定义中不实例化对象;它只是声明它,其方式与文件范围内的extern WordCloud wc;
不会实例化该类完全相同。事实上,静态成员变量本质上与 extern 全局变量相同,只是它们的名称和访问控制规则基于它们所在的类。您是否确实在某些
中实例化了静态成员变量.cpp
文件包含:那么你就会得到一个错误。当然,您可以传入构造函数参数来解决此问题:
请注意,如果您根本不实例化该变量,那么当您尝试在其他地方引用它时,您当然会收到链接器错误。
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:As for why the
static
change suppressed the error, the declarationstatic WordCloud wc;
in the class definition does not instantiate the object; it merely declares it, in exactly the same way that anextern WordCloud wc;
at file scope would not instantiate the class. Indeed, static member variables are essentially the same asextern
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:Then you would have got an error. Of course, you could pass in constructor parameters to resolve this:
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.
您对编译器为何寻找默认构造函数的猜测是正确的;您没有在
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 aFontTestingApp
constructor.As for why the
static
approach "works"; it doesn't. Static member declarations must also be accompanied by definitions (typically along the lines ofWordCloud 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.
由于您提供了自定义构造函数(对于
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 classFontTestingApp
) you construct the member correctly in the initializer list.如果您声明带参数的构造函数并想使用不带参数的构造函数,则必须显式声明最后一个。但是您不使用带参数的 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:
Using "static" statement is only declaration of data member but not definition. That's why your code compiled without errors.
如果您使用非默认构造函数,则必须定义一个默认构造函数。当成员是静态的时,除非您显式定义它(而不是声明它),否则不会为其分配内存,这可能就是您没有收到错误的原因。
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.
我猜问题在于 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.
您不得将 wc 成员设置为静态。
您必须从 FontTestingApp 构造函数的初始化列表中显式调用类的构造函数,如下所示:
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: