【问题标题】:Calling a non-virtual function in derived class using a base class pointer使用基类指针在派生类中调用非虚函数
【发布时间】:2013-05-15 13:45:42
【问题描述】:

this answer中所述:

高度依赖 dynamic_cast 通常表明您的设计出了问题。

我想知道的是如何在派生类中调用自定义函数,基类中没有同名函数,但是使用基类指针并且可能没有@987654322 @如果事实上有更好的方法。

如果这个函数是两个都定义的虚函数,那很容易。但这只是派生类独有的功能。

也许dynamic_cast毕竟是最好的方式?

【问题讨论】:

  • 嗯,你想做你想做的事,这表明你的设计可以通过返工来做。如果您需要,请使用dynamic_cast
  • 也许只有我一个人,但我怀疑你的设计有点错误。
  • 出于兴趣,什么样的场景需要你这样做?
  • 如果你真的想这样做,你应该问问自己,你是否真的在处理正确的类型。如果代码设计为与基类一起使用,那么您应该与基类一起使用,并且如果您到处都必须问“可能是这种类型,那么就这样做”,这只是您错误的类型级别工作。
  • @Muckle_ewe:最可能的情况是,如果您使用基类指针导航到一个对象,然后需要做一些未通过基类公开的事情。 RTTI 是解决该问题的一种选择,其他方法是胖基类、访问者模式或重新设计的导航方案。

标签: c++ polymorphism


【解决方案1】:

为了调用Derived 类的函数,你必须获得一个指向派生类的指针。作为一种选择(视情况而定),您可能希望使用static_cast 而不是dynamic,但正如您所说:

it is often an indication your design has gone wrong

另外,有时我认为可以使用强制转换。当我为游戏设计 GUI 库时,它有一个基类 Widget 和许多子类。在编辑器中制作了一个实际的窗口布局,后来一些Loader 类正在夸大这个布局。为了从布局中填充每个小部件数据(游戏相关)的实际特定小部件,我制作了一种从小部件中查询小部件子级的方法。此函数将Widget* 重新调整,然后我将dynamic_casted 调整为实际类型。我还没有找到更好的设计。

后来我还发现Android 上的 GUI 系统工作方式相同

【讨论】:

【解决方案2】:

我想知道的是如何在派生类中调用自定义函数...如果没有dynamic_cast,如果实际上有更好的方法

正如引用中所指出的,这是一个设计问题,而不是实施问题。没有“更好的方法”来调用该函数; “更好的方法”是重新设计你的类型,这样子类型就不需要向它们的父类型添加功能。通过这样做,您的类型满足(一种常见的解释)里氏替换原则,并且更易于使用,因为用户根本不需要了解子类型。

如果以这种方式重新设计类型是不可能或异常困难的,那么也许您确实需要 RTTI。该建议没有说“所有使用 ...”,只是“高度依赖 ...”,这意味着 RTTI 应该是最后的手段,而不是默认方法。

【讨论】:

    【解决方案3】:

    这更像是一个选项而不是一个真正的答案,所以不要用石头砸死我。

    class Derived;
    
    class Base
    {
    public:
    
       virtual Derived * getDerived()const
       {
           return NULL;
       }
    };
    
    class Derived : public Base
    {
    public:
    
       virtual Derived * getDerived()const
       {
           return this;
       }
    };
    

    我猜你明白了……

    附:迈克·西摩,谢谢 :-)

    【讨论】:

    • @DyP:在没有成熟的 RTTI 的情况下从基类访问少量潜在的派生类可能是一个有用的技巧;尽管您需要返回实际的子类型而不是 void* 以使其更加安全。不过,它的扩展性不是很好。
    • @MikeSeymour 您仍然必须将void* 转换为Derived*,所以我看不出这与@ 的函数成员中的static_cast<Derived*>(this)(或reinterpret_cast)有何不同987654327@.
    • @DyP:确实,这就是为什么我说它应该返回实际的子类型而不是 void* 以使其更加安全。
    猜你喜欢
    • 2015-04-16
    • 2018-10-21
    • 2012-08-08
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    相关资源
    最近更新 更多