我是C/C++新手
我试着实现单例模式。
为什么下面的代码不编译。在javascript中,以类似的方式实现单例模式没有问题。(https://addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript)
我认为当我声明指针*singleton_instance static时,静态方法可以访问它。但是G++给出了错误
singleton_pattern_nullptr.cpp:12:20: warning: ‘constexpr’ needed for in-class initialization of static data member ‘Grammar* Grammar::singleton_instance’ of non-integral type [-fpermissive]
12 | static Grammar *singleton_instance = NULL;但即使是
#include <iostream>
#include <stdio.h>
#define NULL nullptr
class Grammar {
protected:
Grammar() {};
Grammar(const Grammar&) = delete;
Grammar& operator=(const Grammar&) = delete;
static Grammar *singleton_instance = NULL;
public:
Grammar& getInstance();
};
static Grammar& Grammar::getInstance() {
if(singleton_instance == NULL) {
// no star with new
singleton_instance = new Grammar();
}
return *singleton_instance;
}
int main(int argc, char* argv[]) {
Grammar *grammar;
grammar = Grammar::getInstance();
return 0;
}现在当我定义
static constexpr Grammar *singleton_instance = NULL;g++产生错误信息.
singleton_pattern_nullptr.cpp:23:23: error: assignment of read-only variable ‘Grammar::singleton_instance’
23 | singleton_instance = new Grammar();但还是..。
singleton_pattern_nullptr.cpp:33:34: error: cannot call member function ‘Grammar& Grammar::getInstance()’ without object
33 | grammar = Grammar::getInstance();我以为我可以把它变成mutable,但是在这个线程(C++中的静态可变成员变量?)中,我读到不应该需要指定静态成员变量才能成为(可变的),因为无论如何都应该是这样的。
因此,请告诉我我的错误在哪里,以及是否可以在C++中实现像我上面想的那样的单例(请参阅javascript示例)。
谢谢
编辑:
到目前为止,我已经承认了目前的答案,但我仍然不知道自己做错了什么。如果可能的话,请告诉我如何更改指针*singleton_instance和Grammar::getInstance(),以便我可以根据这个想法操作指针。现在,我已经沮丧地声明了这两种静态,并根据*singleton_instance的错误消息用修饰符constexpr声明了g++。
不会那么难吧?
另一个例子:https://developer-blog.net/singleton-design-pattern-in-c/
谢谢
编辑2:
感谢M47发布了一篇实用的"Meyers Singleton“(作为用户idclev 463035818的注释)
但是,尽管我设置了标志-std=c++17,编译器仍然使用警告进行响应。
**singleton_pattern.h:9:12:** warning: inline variables are only available with ‘-std=c++17’ or ‘-std=gnu++17’
9 | static inline Grammar *singleton_instance = nullptr;但请允许我三(两?)请更多关于c++的理解问题。
1-在头文件中,方法声明为static inline。
static inline Grammar *singleton_instance = nullptr;然而,在定义中,您传递了这些“修饰符”(?)。或者是通过名称空间/类运算符static在定义中隐含了static inline还是同时隐含了::?我想我在某个地方读过类似的书。
Grammar& Grammar::getInstance()如果不是这样的话,那么我就知道头文件声明和cpp文件定义中的发散修饰符上有线程。能给我个提示吗?
最后但并非最不重要的(小问题)我收到警告
warning: variable ‘grammar’ set but not used [-Wunused-but-set-variable]非常感谢您向我展示了如何使单例模式的指针版本工作!荣誉!
发布于 2020-11-08 13:55:11
不需要将静态实例显式声明为成员变量。你也可以:
class Grammar
{
public:
Grammar() {}
Grammar(const Grammar&) = delete;
Grammar& operator=(const Grammar&) = delete;
static Grammar& Grammar::getInstance() {
static Grammar instance;
return instance
}
};这样还可以避免直接使用原始指针、潜在的分段错误和SIOFs。尽管如此,根据C++核心指南,不推荐单例范例。
注意,我删除了前两行中的复制构造函数和赋值。这通常是在单例范例中完成的,以避免不必要的副本。
编辑:用指针进行编辑
// header file:
class Grammar {
protected:
Grammar() {};
Grammar(const Grammar&) = delete;
Grammar& operator=(const Grammar&) = delete;
static inline Grammar *singleton_instance = nullptr;
public:
static Grammar& getInstance();
};
// cpp file
Grammar& Grammar::getInstance() {
if (singleton_instance == nullptr) {
// no star with new
singleton_instance = new Grammar();
}
return *singleton_instance;
}
// main.cpp
#include "grammar.h"
int main(int argc, char* argv[]) {
Grammar *grammar;
grammar = &Grammar::getInstance();
return 0;
}静态内联成员变量仅在C++17中定义。另一种方法是在类之外初始化静态成员。它必须在一个和唯一一个翻译单位完成。这可能会导致SIOFs:
// cpp file
#include "grammar.h"
Grammar* Grammar::singleton_instance = nullptr;
...https://stackoverflow.com/questions/64738644
复制相似问题