CallingClass::CallingFunc()
{
SomeClass obj;
obj.Construct(*Singleton::GetInstance()); // passing the listener
// Singleton::GetInstance() returns a static pointer.
//Singleton is derived from IListener
}
SomeClass::Construct(const IListener &listener)
{
IListener* pListener = const_cast<IListener*>(&listener);
}
const_cast
pListener
为空后。
是否有可能进行类型转换?
由于
答案 0 :(得分:10)
让我看看。你有两阶段初始化,一个Singleton,和抛弃const
,和你要取消引用一个对象只是为了再次获取它的地址?一个迷路的NULL指针是你关心的最少,我的朋友。
扔掉它并从头开始再写。并首先拿起一本C ++书。
您知道,const_cast
除非传递了空指针,否则无法生成空指针。 GetInstance()
必须返回NULL
才能产生此行为,一旦您取消引用它就会正式为UB。
答案 1 :(得分:1)
const_cast基本上是编译器忽略某些东西的指令。应避免使用它,因为您正在覆盖编译器保护,并且当您编写试图更新只读内存的内容时,它可能导致崩溃。
但是,它实际上并不会导致生成任何代码。
因此,如果这样:
IListener* pListener = const_cast<IListener*>(&listener);
导致pListener为NULL,然后&amp; listener为NULL,这是不可能的(或者你为你的单例返回一个空引用,或者你从问题描述中遗漏了一些东西)。
说完我同意DeadMG的回答。
应避免创建空对象并对其执行Init(两阶段构造)。正确创建的对象应该是有效的,如果你有一个Init方法,它就不是。
应避免从任何事物中删除常量 - 它极有可能产生令人惊讶的行为。
该代码中的去重新引用量会给任何人带来麻烦。
答案 2 :(得分:0)
两个问题:
不希望自己不仁慈,我会诚实地说,重新开始可能会更好。我对这段代码有几个问题:
首先,Singleton模式应确保只创建一个特定对象,因此它通常由指针,引用或其衍生物(即boost共享指针等)返回。它不一定是const而是它在这里的事实表明作者并不打算以非常规的方式使用它。
其次,您通过引用将此对象传递给函数。没必要。这是单例模式的主要特征(和缺点)之一:您可以从任何地方访问它。所以你可以轻松地写一下:
SomeClass::Construct()
{
IListener* pListener = const_cast<IListener*>(*Singleton::GetInstance());
}
虽然这对你来说仍然没有帮助。它做的一件事是让你的界面更清晰。你知道,当你写SomeClass::Construct(const IListener&listener)
时,任何阅读你的人都可以合理地暗示listener
在函数中被视为const
并使用const_cast
,你已经打破了隐含合同。 这是一个非常好的理由,您不应该使用const_cast
- 至少在这种情况下不会这样做。
您需要问自己的基本问题是,当您的IListener
是const时,为什么需要在Construct
内以非常规方式使用它?单例不应该返回const对象,否则你的函数不应该需要非const。
这是一个设计问题,您需要在采取任何进一步措施之前进行整理。