首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我的单例实现不编译?(C++)

为什么我的单例实现不编译?(C++)
EN

Stack Overflow用户
提问于 2020-11-08 13:32:44
回答 1查看 404关注 0票数 0

我是C/C++新手

我试着实现单例模式。

为什么下面的代码不编译。在javascript中,以类似的方式实现单例模式没有问题。(https://addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript)

我认为当我声明指针*singleton_instance static时,静态方法可以访问它。但是G++给出了错误

代码语言:javascript
复制
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;

但即使是

代码语言:javascript
复制
#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;
}

现在当我定义

代码语言:javascript
复制
static constexpr Grammar *singleton_instance = NULL;

g++产生错误信息.

代码语言:javascript
复制
singleton_pattern_nullptr.cpp:23:23: error: assignment of read-only variable ‘Grammar::singleton_instance’
   23 |    singleton_instance = new Grammar();

但还是..。

代码语言:javascript
复制
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_instanceGrammar::getInstance(),以便我可以根据这个想法操作指针。现在,我已经沮丧地声明了这两种静态,并根据*singleton_instance的错误消息用修饰符constexpr声明了g++。

不会那么难吧?

另一个例子:https://developer-blog.net/singleton-design-pattern-in-c/

谢谢

编辑2:

感谢M47发布了一篇实用的"Meyers Singleton“(作为用户idclev 463035818的注释)

但是,尽管我设置了标志-std=c++17,编译器仍然使用警告进行响应。

代码语言:javascript
复制
**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

代码语言:javascript
复制
static inline Grammar *singleton_instance = nullptr;

然而,在定义中,您传递了这些“修饰符”(?)。或者是通过名称空间/类运算符static在定义中隐含了static inline还是同时隐含了::?我想我在某个地方读过类似的书。

代码语言:javascript
复制
Grammar& Grammar::getInstance()

如果不是这样的话,那么我就知道头文件声明和cpp文件定义中的发散修饰符上有线程。能给我个提示吗?

最后但并非最不重要的(小问题)我收到警告

代码语言:javascript
复制
warning: variable ‘grammar’ set but not used [-Wunused-but-set-variable]

非常感谢您向我展示了如何使单例模式的指针版本工作!荣誉!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-08 13:55:11

不需要将静态实例显式声明为成员变量。你也可以:

代码语言:javascript
复制
class Grammar
{
public:
    Grammar() {}
    Grammar(const Grammar&) = delete;
    Grammar& operator=(const Grammar&) = delete;
    static Grammar& Grammar::getInstance() {
        static Grammar instance;
        return instance
    }
};

这样还可以避免直接使用原始指针、潜在的分段错误和SIOFs。尽管如此,根据C++核心指南,不推荐单例范例。

注意,我删除了前两行中的复制构造函数和赋值。这通常是在单例范例中完成的,以避免不必要的副本。

编辑:用指针进行编辑

代码语言:javascript
复制
// 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:

代码语言:javascript
复制
// cpp file
#include "grammar.h"
Grammar* Grammar::singleton_instance = nullptr;
...
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64738644

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档