【问题标题】:const_cast failing in c++const_cast 在 C++ 中失败
【发布时间】:2012-08-08 12:09:14
【问题描述】:
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 之后为空。 是否可以执行这种类型转换?

谢谢

【问题讨论】:

  • 究竟是什么失败了?你在编译时有问题吗?运行?我看不出SomeClass::Construct 成员函数有什么问题。
  • 你是认真的吗,一个GetInstance(),它返回一个指向singleton的指针????哎呀,这就是丑陋代码的缩影!
  • const_cast pListener 为空后。
  • 我认为 const_cast 可能必须在 &amp; 运算符之后移动,但现在无法测试。在您尝试抛弃const 之前,您已经在询问const 引用的地址,这很奇怪。
  • @TonyTheLion:很抱歉,单例不是这样写的。我不明白你的担忧。你能详细说明一下吗?

标签: c++ const-cast


【解决方案1】:

那么让我看看。你有两阶段初始化,一个单例,抛弃const你取消引用一个对象只是为了再次获取它的地址?我的朋友,流浪的 NULL 指针是最少的。

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

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

【讨论】:

  • 虽然这并不能远程回答问题,但我还是忍不住+1。
  • GetInstance() 不返回 null。我检查了它。我需要取消引用,因为 Construct 将引用作为参数。你能建议这样做的正确方法吗?我是编程新手。
  • @DeadMG:感谢您的回复,我完全无法控制构造方法。它是一个平台的 API。我刚刚制作了一个传递单例引用的应用程序,这样我就可以在应用程序的任何地方处理回调。我想知道的是我们可以在静态指针上执行 const_cast 吗? – yogesh singh 36 秒前
【解决方案2】:

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

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

因此,如果这样:

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

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

话虽如此,我非常同意 DeadMG 的回答。

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

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

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

【讨论】:

  • 你可能应该提到“上面的答案”是谁写的,因为顺序有时会改变。
  • 哦,是的,我忘了它是这样做的。谢谢
  • @RyanAmos:感谢您的回复,我完全无法控制构造方法。它是一个平台的 API。我刚刚制作了一个传递单例引用的应用程序,这样我就可以在应用程序的任何地方处理回调。我想知道的是我们可以在静态指针上执行 const_cast 吗? – yogesh singh 36 秒前
  • 您可以对静态指针执行 const_cast。但是,仅仅因为您可以做某事并不意味着您应该做。
  • @TomTanner:我已经调试和检查过了。我的单身人士没有返回 null。只有在转换后它才变为空。我只是想知道是什么导致了这种情况发生?
【解决方案3】:

两个问题:

  1. 您想在这里实现什么目标?
  2. 您对代码有多少控制权? (即你能改变什么?)

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

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

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

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

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

您需要问自己的基本问题是,当您的 IListener 为 const 时,为什么您需要在 Construct 中以非 const 方式使用它?不返回 const 对象,否则您的函数不需要它是非常量的。

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

【讨论】:

  • :感谢您的回复,我完全无法控制Construct Method。它是一个平台的 API。我刚刚制作了一个传递单例引用的应用程序,以便我可以在应用程序的任何位置处理回调。我想知道的是我们可以在静态指针上执行 const_cast 吗?
  • 那么你是说你被别人的代码困住了,它接受一个 const 引用,然后抛弃 const 使其成为非常量指针?如果是这样,您应该告诉他们他们的代码有多糟糕,并且您应该出于上述原因要求他们更改它。至于您的问题,将const_cast 应用于静态指针没有区别。
猜你喜欢
  • 2018-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-03
  • 2011-04-17
  • 2019-08-22
  • 1970-01-01
相关资源
最近更新 更多