关于 C++ 的使用单例类

发布于 2025-01-06 07:19:31 字数 942 浏览 3 评论 0原文

我已经查看了关于单例类实现的此线程,但不清楚如何实现在实践中使用它。为了使上下文更具体,假设我有一个输入流 std::istream 实例,许多不同的类需要访问该实例,但我不是将其传递给每个类构造函数,而是考虑使用单例类 Connection 来包装此信息。所以客户可以打电话:

Connection.getInstance().get_input_stream();

我的问题有两个:(1)这是单例类的正确使用(2)来实现这个,我尝试过这样的事情:

class Connection {
public:
    static Connection& getInstance() {
        static Connection instance; // Guaranteed to be destroyed   
        return instance;
    }
    std::istream& get_istream() {
        return is;
    }

    void set_istream(std::istream & stream) {
            is = stream;
    }
private:
    std::istream& is;
}

首先,这个代码由于某种原因无法编译。其次,在它可用之前必须调用 set_istream() 感觉很尴尬。有更好的方法来完成这件事吗?谢谢。

编辑:显然,正如你们许多人指出的那样,尝试分配参考是我愚蠢的行为。第二部分是如何将流信息传递到单例中 - 这似乎不值得,这表明这可能是使用它的错误情况。谢谢大家的回答。

I have looked at this thread on singleton class implementation, but not clear on how to use it in practice. To make the context more concrete, say I have a input stream std::istream instance that many different class need to access, but instead of passing it in for each class constructor, I am thinking of using a singleton class Connection to wrap this info. So a client can just call:

Connection.getInstance().get_input_stream();

My questions are two fold: (1) is this a proper use of singleton class (2) on implementing this, I have tried something like this:

class Connection {
public:
    static Connection& getInstance() {
        static Connection instance; // Guaranteed to be destroyed   
        return instance;
    }
    std::istream& get_istream() {
        return is;
    }

    void set_istream(std::istream & stream) {
            is = stream;
    }
private:
    std::istream& is;
}

First this code doesn't compile for some reason. Second it feels awkward that you have to call set_istream() before it is usable. Is there a better way to get this done? Thanks.

EDIT: Apparently, trying to assign a reference is my silly doing, as many of you pointed out. The second part is how to pass in stream information into singleton - it seems not worth it, which suggests this might be a wrong case for using it. thanks you all for your answers.

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

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

发布评论

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

评论(3

痴情 2025-01-13 07:19:31

创建后无法修改引用,因此要“设置”istream,您必须

class Connection {

    /* ... */

    Connection(std::istream & stream) : is(stream) {}
private:
    std::istream& is;
}

将其传递给 ctor:但是,这会产生一个问题,即当您创建一个静态实例——答案是它并不简单(充其量)。您可以使用指针而不是引用,因此您可以创建一个对象并稍后将其指向实际流,但此时您基本上是在自找麻烦(需要两阶段初始化)。

最终,这是不值得的。我的建议是完全反对在这种情况下使用单例。看起来它增加了相当多的工作,但提供的回报却很少(如果有的话)。

相当多的人开始建议完全不要使用单例,至少在 C++ 中是这样,坦率地说,我在大多数情况下倾向于同意。这种情况就是为什么——你所做的工作通常最终得不到什么回报。

A reference can't be modified after creation, so to "set" the istream, you'd have to pass it to the ctor:

class Connection {

    /* ... */

    Connection(std::istream & stream) : is(stream) {}
private:
    std::istream& is;
}

That raises a problem, however, of how you pass the correct stream to the ctor when you're creating a static instance -- and the answer to that is that it's non-trivial (at best). You could use a pointer instead of a reference, so you can create an object and point it at an actual stream later, but at that point you're basically asking for trouble (requiring two-stage initialization).

Ultimately, it's just not worth it. My advice would be against using singleton in this case at all. It looks like it's adding quite a bit of work, and providing little (if anything) in return.

Quite a few people are starting to advise against using singletons at all, at least in C++, and quite frankly, I tend to agree most of the time. This kind of situation is why -- you usually end up with little in return for the work you do on it.

∞觅青森が 2025-01-13 07:19:31

我总是被告知要避免单例,所以这有两个部分:

class Connection {
public:
    static std::istream& getInstance() {
        assert(is);
        return *is;
    }    
    static void set_istream(std::istream & stream) {
            is = &stream;
    }
private:
    static std::istream* is;
}
std::istream* Connection::is = NULL;

int main() {
    Connection::set_istream(std::cin);
    Connection::getInstance() << "moomoomoo\n";
}

注意我将流静态化,指针和全局(所以它实际上是单例。你的代码......是没有理由放置那么多引用,如果您有 is = blah,其中 is 是引用,则不会重新放置该引用。 它会复制右边。左边,这对于流来说没有意义,甚至无法编译。

当然,使用全局变量或非单例变量(这是全局变量,只能创建一次)。

//params are ignored after first call
template<typename... Ts>
std::istream& Connection(Ts... Us) { 
    static std::ifstream c(std::forward<Ts>(Us)...);
    return c;
}

int main() {
   //construct and use
   Connect("input.txt") << "thing" << std::endl;
   Connect() << "stuff";
   Connect("this is ignored") << "IM A COW STOP SAYING IM A DUCK";
}

I've always been told to avoid singletons, so there's two parts to this:

class Connection {
public:
    static std::istream& getInstance() {
        assert(is);
        return *is;
    }    
    static void set_istream(std::istream & stream) {
            is = &stream;
    }
private:
    static std::istream* is;
}
std::istream* Connection::is = NULL;

int main() {
    Connection::set_istream(std::cin);
    Connection::getInstance() << "moomoomoo\n";
}

Note I made the stream static, a pointer, and global (so it's actually a singleton. Your code.... wasn't. There's no reason to have that many references laying around, and if you have is = blah where is is a reference, that does not reseat the reference. It would copy the right to the left, which for streams, doesn't make sense and wouldn't even compile.

Of course, singletons are bad. Use globals, or non-singletons. (This is a global, which is only creatable once)

//params are ignored after first call
template<typename... Ts>
std::istream& Connection(Ts... Us) { 
    static std::ifstream c(std::forward<Ts>(Us)...);
    return c;
}

int main() {
   //construct and use
   Connect("input.txt") << "thing" << std::endl;
   Connect() << "stuff";
   Connect("this is ignored") << "IM A COW STOP SAYING IM A DUCK";
}
话少情深 2025-01-13 07:19:31

它无法编译有两个原因。首先,调用语法有一个非常小的问题。像这样修复它:

Connection::getInstance().get_input_stream();

第二个是你不能分配给引用,它必须在构造时初始化。由于您的构造函数是从 getInstance 的中间调用的,因此这是不切实际的。请改用指针。

是的,在单例可用之前需要调用 set_istream 很尴尬,但这似乎是不可避免的。

It doesn't compile for two reasons. First you have a very minor problem with the calling syntax. Fix it like this:

Connection::getInstance().get_input_stream();

Second is that you can't assign to a reference, it must be initialized at construction time. Since your constructor is called from the middle of getInstance, that's impractical. Use a pointer instead.

Yes it's awkward to need to call set_istream before your singleton is usable, but that seems unavoidable.

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