【问题标题】:How can I prevent this kind of casting in c++如何在 C++ 中防止这种类型的转换
【发布时间】:2011-04-15 08:39:58
【问题描述】:

假设有两个这样的类

class Locator
{
public:
// this goes to the specified latitide and longitude
bool GoToLocation(long lat, long longtd);
};

class HouseLocator : private Locator
{
public:
// this internally uses GoToLocation() after fetching the location from address map
bool GoToAddress(char *p);
}

我使用私有继承来阻止 HouseLocator 上的 GoToLocation(),因为它在那里没有意义,并迫使人们使用正确的接口。

现在我的问题是,我怎样才能防止这种类型的转换?

HouseLocator *phl = new HouseLocator;
Locator *pl = (Locator*)phl;
pl->GoToLocation(10, 10);

我是否应该只记录不这样做并将其余的留给用户,我的意思是,如果他做出错误的演员表,那是他的问题吗?

【问题讨论】:

  • 你无法阻止它。如果您不希望它工作,并且没有意义,为什么不让 HouseLocator 包含定位器,而不是从它继承?
  • 无论您做什么,人们都可以使用例如:特定于平台的技巧。像你一样使用私有继承就足够了 - 你清楚地表明不应该使用Locator 接口,如果用户想要破坏东西,那不是你的问题。
  • 查看stackoverflow.com/questions/5650790/… 的答案,了解一些可以帮助您的 GCC 选项。
  • 丑陋的解决方案编号 XXX... 更改基类,使 GoToLocation 是虚拟的,并在 HouseLocator 中覆盖它以抛出 NotSupportedException...。
  • @forsvarir : 呃.. 编译时问题的运行时错误?到那时,为什么首先要使用静态类型语言?

标签: c++ inheritance casting


【解决方案1】:

使用组合而不是继承:

class Locator
{
public:
    bool GoToLocation(long lat, long longtd);
};

class HouseLocator
{
    Locator locator_;
public:
    // internally uses locator_.GoToLocation()
    bool GoToAddress(char *p);
};

如果由于某种原因这不切实际,那么使用 private 继承是你最好的选择——如果用户将 HouseLocator* 转换为 Locator* 他们是调用未定义的行为,这是他们的问题,而不是你的问题。

【讨论】:

  • 我认为这是最合适的,尽管有一些变化。谢谢。
【解决方案2】:

如果你可以改变基类,你可以用protected代替public

否则,您无能为力,只能告诉人们不要这样做。

【讨论】:

    【解决方案3】:

    你不能。 C 转换包含 reinterpret_cast 功能,您无法阻止任何两种数据指针类型之间的 reinterpret_casting。

    请注意,在某些多重继承情况下,强制转换不会进行所需的调整,因此可能无法达到预期的结果。 (static_cast 将进行调整,但会检查可访问性)。

    【讨论】:

      【解决方案4】:

      这看起来好像HouseLocator 可能不应该派生自Locator。在有限的上下文中,您可能想要 使用 定位器的东西(即,它作为私有成员变量组成)。

      私有继承几乎专门用作组合设备,当您不能直接组合时(因为您还需要专门化类)。

      当您想要某种类型的异构集合并且您希望将它们全部视为相同(或在类似情况下)时,通常使用继承。如果您以需要知道派生类型的方式使用派生类,那么继承实际上通常会损害您的设计,因为它是最紧密的耦合形式(必须构造在一起,不能反弹)。

      【讨论】:

        【解决方案5】:

        恕我直言,不值得尝试阻止它。用户无论如何都可以做Locator* p = new Locator(); p->GoToLocation(10,10);

        【讨论】:

          【解决方案6】:

          你也可以转换运算符

          operator Locator() const;
          

          在 HouseLocator 类中引发异常。但这不会阻止 reinterpret_cast 的转换。没有什么能阻止它。

          【讨论】:

            猜你喜欢
            • 2013-10-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-02-24
            • 1970-01-01
            • 1970-01-01
            • 2020-02-07
            • 1970-01-01
            相关资源
            最近更新 更多