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
(或其他)是