-2
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为空。是否可以执行这种类型转换?

谢谢

4

3 回答 3

10

所以让我看看。你有两阶段初始化,一个 Singletoncast away const并且你取消引用一个对象只是为了再次获取它的地址?我的朋友,流浪的 NULL 指针是您最不关心的问题。

扔掉它,然后从头开始重新编写。并先拿起一本 C++ 书。

就像你知道的那样,const_cast除非它被传递一个,否则不能产生一个空指针。GetInstance()必须返回NULL以产生这种行为,一旦你取消引用它,它就正式成为 UB。

于 2012-08-08T12:14:54.233 回答
1

const_cast 基本上是对编译器的一条指令,以忽略某些东西的 const 性。应避免使用它,因为您正在覆盖编译器保护,并且当您编写尝试更新只读内存的内容时,它可能会导致崩溃。

但是,它实际上不会导致生成任何代码。

因此,如果这样:

IListener* pListener = const_cast<IListener*>(&listener);

导致 pListener 为 NULL,然后 &listener 为 NULL,这是不可能的(或者您正在为单例返回空引用,或者您在问题描述中遗漏了某些内容)。

话虽如此,我强烈同意 DeadMG 的回答。

应避免创建一个空对象并对其进行初始化(两阶段构造)。正确创建的对象应该是有效的,如果你有一个 Init 方法,它不是。

应避免从任何事物中删除 constness - 它极有可能产生令人惊讶的行为。

该代码中的去引用和引用的数量会让任何人头疼。

于 2012-08-08T12:47:35.360 回答
0

两个问题:

  1. 你想在这里达到什么目的?
  2. 你对代码有多少控制权?(即你能改变什么?)

不想不友善,我会诚实地说,重新开始可能会更好。这段代码有几个问题:

首先,单例模式应该确保只创建一个特定对象,因此它通常由指针、引用或其派生类返回(即 boost 共享指针等)。尽管它不一定是 const 并且事实上它在这里表明作者不打算以非常量方式使用它。

其次,您将通过引用将此对象传递给函数。没必要。这是单例模式的主要特性(和缺点)之一:您可以从任何地方访问它。所以你可以很容易地写:

SomeClass::Construct()
{
    IListener* pListener = const_cast<IListener*>(*Singleton::GetInstance());
}

虽然这仍然不能真正帮助你。它所做的一件事就是让你的界面更清晰一些。你看,当你写SomeClass::Construct(const IListener&listener)任何阅读你的人时,你可以合理地暗示这listener被视为const在函数内,并且通过使用const_cast,你已经打破了那个隐含的合同。这是你不应该使用的一个很好的理由const_cast——至少在这些情况下不应该使用。

您需要问自己的基本问题是,当您IListener是 const 时,为什么需要在 const 内以非 const 方式使用它Construct单例不应该返回一个 const 对象,或者你的函数不应该需要它是非常量的。

这是一个设计问题,您需要在采取任何进一步措施之前加以解决。

于 2012-08-08T12:53:03.627 回答