C++ C++;单例类

C++ C++;单例类,c++,singleton,C++,Singleton,我已经研究了单例类的实现,但不清楚如何在实践中使用它。为了使上下文更具体,假设我有一个输入流std::istream实例,许多不同的类都需要访问它,但是我没有将它传递给每个类构造函数,而是考虑使用一个单例类连接来包装此信息。因此,客户只需调用: Connection.getInstance().get_input_stream(); 我的问题有两个:(1)这是对singleton类的正确使用吗(2)在实现这一点时,我尝试过这样的方法: class Connection { public:

我已经研究了单例类的实现,但不清楚如何在实践中使用它。为了使上下文更具体,假设我有一个输入流
std::istream
实例,许多不同的类都需要访问它,但是我没有将它传递给每个类构造函数,而是考虑使用一个单例类
连接来包装此信息。因此,客户只需调用:

Connection.getInstance().get_input_stream();
我的问题有两个:(1)这是对singleton类的正确使用吗(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;
}
Connection::getInstance().get_input_stream();
首先,由于某种原因,此代码无法编译。其次,在可用之前必须调用
set\u istream()
,这让人感到尴尬。有没有更好的方法来完成这件事?谢谢


编辑:很显然,正如你们中的许多人所指出的,试图分配一个引用是我愚蠢的行为。第二部分是如何将
信息传递到singleton中——这似乎不值得,这表明使用它可能是错误的。谢谢大家的回答。

我一直被告知要避免单身,所以这里有两个部分:

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

我一直被告知要避免单身,所以这里有两个部分:

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

创建后无法修改引用,因此要“设置”istream,必须将其传递给ctor:

class Connection {

    /* ... */

    Connection(std::istream & stream) : is(stream) {}
private:
    std::istream& is;
}
然而,这就产生了一个问题,即在创建静态实例时,如何将正确的流传递给ctor——答案是,这是非常重要的(最多)。您可以使用指针而不是引用,因此您可以创建一个对象,稍后将其指向实际流,但在这一点上,您基本上是在自找麻烦(需要两个阶段的初始化)

最终,这是不值得的。我的建议是在这种情况下根本不要使用单例。看起来它增加了很多工作,但回报很少(如果有的话)


有不少人开始建议不要使用<代码> SUNLTONG//COS>S,至少在C++中是这样,坦白地说,我大部分时间都同意。这种情况就是为什么——通常情况下,您对其所做的工作几乎没有回报。

引用在创建后无法修改,因此要“设置”istream,您必须将其传递给ctor:

class Connection {

    /* ... */

    Connection(std::istream & stream) : is(stream) {}
private:
    std::istream& is;
}
然而,这就产生了一个问题,即在创建静态实例时,如何将正确的流传递给ctor——答案是,这是非常重要的(最多)。您可以使用指针而不是引用,因此您可以创建一个对象,稍后将其指向实际流,但在这一点上,您基本上是在自找麻烦(需要两个阶段的初始化)

最终,这是不值得的。我的建议是在这种情况下根本不要使用单例。看起来它增加了很多工作,但回报很少(如果有的话)


有不少人开始建议不要使用<代码> SUNLTONG//COS>S,至少在C++中是这样,坦白地说,我大部分时间都同意。这种情况就是为什么——通常,您在它上所做的工作几乎没有回报。

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

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;
}
Connection::getInstance().get_input_stream();
第二,您不能分配给引用,它必须在构造时初始化。因为构造函数是从getInstance的中间调用的,所以这是不切实际的。改用指针


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

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

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;
}
Connection::getInstance().get_input_stream();
第二,您不能分配给引用,它必须在构造时初始化。因为构造函数是从getInstance的中间调用的,所以这是不切实际的。改用指针


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

它无法编译,因为您试图分配给引用变量。您只能在构造函数的初始值设定项列表中初始化它。可能的重复项也要使用它,您需要使用静态方法访问器,如Connection::getInstance()。get_input_stream()@米凯瑟莫尔:虽然非常相关,但甚至不接近重复。@MooingDuck:它回答了第一个问题;剩下的问题只有在OP决定忽略它时才相关。它不会编译,因为您试图分配给引用变量。您只能在构造函数的初始值设定项列表中初始化它。可能的重复项也要使用它,您需要使用静态方法访问器,如Connection::getInstance()。get_input_stream()@米凯瑟莫尔:虽然非常相关,但甚至不接近重复。@MooingDuck:它回答了第一个问题;剩下的问题只有在OP决定忽略它的情况下才有意义。你的代码无法工作-你没有在getInstance中向构造函数传递参数。我想避免单例-关于公共构造函数()的一个问题是,当Connection()被多次调用时,它仍然是单例类吗?@Oliver:事实上,您通常会将ctor设置为私有(这是我显示它的方式,尽管默认情况下是私有的,而不是显式指定的)。单例几乎总是需要ctor private,因此静态
GetInstance
(或其他)是创建单例的唯一方法。您的代码不起作用-您没有在GetInstance中向构造函数传递参数。我明白了避免单例的要点-但有一个关于公共构造函数()的问题,当Connection()被多次调用时,它仍然是一个单例类吗?@Oliver:事实上,您通常会将ctor设置为private(这就是我显示它的方式,尽管默认情况下是private而不是显式指定的)。单例几乎总是需要ctor private,因此静态
GetInstance
(或其他)是