C++Singleton类返回常量引用
C++ Singleton class returning const reference
我有一个类,它是单例的,定义如下
class myData {
private:
myData (void); // singleton class.
// Copy and assignment is prohibted.
myData (const myData &);
myData & operator=(const myData &);
static myData* s_pInstance;
public:
~myData (void);
static const myData & Instance();
static void Terminate();
void myFunc() { cout << "my function..." ;}
};
//在cpp文件中。
myData* myData::s_pInstance(NULL);
myData::myData(){}
myData::~myData()
{
s_pInstance = NULL;
}
const myData& myData::Instance()
{
if (s_pInstance == NULL)
{
s_pInstance = new myData();
}
return *(s_pInstance); // want to avoid pointer as user may deallocate it, so i used const referense
}
void main() {
(myData::Instance()).myFunc();
}
我得到以下错误
错误C2662:"myData::myFunc":无法将"this"指针从"const myData"转换为"myData&">
如何避免上述问题,并从返回const引用的Instance函数中调用一个函数?
谢谢!
您希望将func()
声明为常量成员函数,这样编译器就知道它不会违反instance()
函数的常量返回值。
相反,您也可以使instance()
函数返回一个与const
函数相同的"正则"引用。
因此,请转向:void myFunc()
转化为void myFunc() const
或者转向:const myData& myData::Instance()
转换为myData& myData::Instance()
如果您在const引用上调用函数,那么您调用的函数也必须是const,在您的情况下是void myFunc() const
。
否则,如果效果更好的话,您可能会返回一个非常量引用。
错误表明myData::Instance()
是该类的常量实例,它不能在此调用myFunc()
,因为myFunc()
可能会更改实例,而您不能更改常量实例。
当然,您知道myFunc()
不能真正更改实例,但您必须宣传这一事实,如下所示:
void myFunc()
const
{ cout << "my function..." ;}
避免讨论Singleton是一个好的模式还是万恶之源,如果你真的在实现Singleton,那么const正确性很可能不会像你预期的那样工作,所以你应该意识到一些陷阱。
首先是您的错误:Instance()
静态成员返回一个const引用,这意味着您只能执行不修改对象的操作,即调用标记为const
的成员函数,或者使用公共成员(如果存在(来不修改其值。我建议的解决方案是修改Instance()
以返回一个非常量引用,而不是像其他人建议的那样使func()
为常量。
现在,当应用于特定的Singleton问题时,对一般的常量正确性问题进行更长的解释。基本问题是,当你实现一个类型时,你将那些修改对象的成员和那些不修改的成员分开,并将后者标记为const
成员函数,这样编译器就知道你的承诺(允许你在常量对象上调用该方法(,并帮助你不破坏它(如果你试图修改方法定义中的状态,就会抱怨(。标记为const
的方法既可以应用于常量对象,也可以应用于非常量对象,但未标记为const
的方法只能应用于非const
的对象。
回到最初的代码段,如果您实现了一个singleton,并且访问对象的唯一方法是通过返回const
引用的Instance()
方法,那么您基本上限制了所有用户代码只能使用接口中实现的const
方法。这意味着,实际上,要么所有方法都是非突变的,要么它们都是无用的(永远不应该使用const_cast
(。这反过来意味着,如果您有任何非常量操作,您希望提供一个返回非常量引用的Instance()
方法。
您可以考虑实现Instance()
的两个变体,但这并没有真正的帮助。重载解决方案无助于用户代码确定使用哪个版本,因此您最终将不得不使用不同的方法:Instance()
、ConstInstance()
(选择您的名称(,这意味着由用户代码决定使用哪个版本。小的优点是,在他们的代码中,访问器的选择将有助于记录他们的预期用途,甚至可能会发现一些错误,但通常情况下,他们只会调用非常量版本,因为它有效。
- 什么时候在C++中返回常量引用是个好主意
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 为什么我可以通过引用修改常量返回
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 将常量指针引用绑定到非常量指针
- 通过常量引用传递参数的矩阵模板类
- 按值捕获引用时出现非常量
- 在C++中使用非常量引用作为常量
- 具有常量引用参数的函数模板专用化
- 多个"常量引用"变量可以共享同一个内存吗?
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 为什么按值传递QStringView比引用常量更快?
- 通过引用常量函数调用另一个类的非常量函数
- 构造常量对象与引用常量对象
- 引用“常量value_type”时出错
- 为什么可以在 for 语句中重新分配引用常量
- 程序反馈:命名循环索引和引用常量数据
- 堆还是栈?在c++中函数调用中引用常量字符串时
- 为什么常量结构数组在按名称引用常量结构时不放在 .rodata 中?
- 为什么编译器允许在函数中发送对迭代器的引用,该函数引用常量迭代器