gpt4 book ai didi

c++ - 如何从返回指向父对象的指针的方法中获取指向子对象的指针

转载 作者:行者123 更新时间:2023-11-28 01:39:54 25 4
gpt4 key购买 nike

上下文

上下文由三个类组成:

  • 抽象父级(例如播放器)
  • child (例如 TapePlayer)
  • 持有者(例如 MyMachine)

holder 有一个成员变量是shared_ptr<...>到父类,它的 setter 接受 shared_ptr<...> child 类。

我的 getter 看起来像这样

shared_ptr<Parent>  getChildPtr() {
return parentPtr;
};

但是它返回一个指向父类的指针,并且不能访问子类方法。
如果我想做类似下面的事情

holder.getChildPtr()->childMethod(); 
// ERROR! No member named 'childMethod' in 'Parent'

我应该如何实现 getter 来获取指向子类而不是父类的指针?

代码

整个代码看起来像这样:

class Player {
public:
Player(){};
virtual ~Player{};

virtual void play() = 0;
}

class TapePlayer : public Player {
public:
TapePlayer(){};
virtual ~TapePlayer{};

void play() { ... };
void rewind() { ... };
}

class MyMachine {
public:
MyMachine(); //
~MyMachine();

void setPlayer(shared_ptr<Player> p) {
playerPtr = p;
}

shared_ptr<Player> getPlayer() {
return playerPtr;
};

private:
shared_ptr<Player> playerPtr;
}


MyMachine machine; // the holder

shared_ptr<TapePlayer> tapePtr(new TapePlayer()); // pointer to child

machine.setPlayer(tapePtr); // set holder with pointer to child

machine.getPlayer()->rewind(); // -- ERROR! No member named 'rewind' in 'Player'
// if I want to get the player of that machine to rewind I need
// to dynamic_cast<TapePlayer>() ...

我很确定有比转换为子类型更好的方法。有什么想法吗?

编辑

这是一个非常简单的例子。我实际上想做的是:

My holder class is named Clip. A clip plays something, be it an image, a video, a sequence of images, some kind of processing with OpenCv, a vector shape... anything that can be displayed.

所有这些类型的东西都是玩家。
我不在乎剪辑中的播放器类型。我只是想让它显示给我看。但是,有些播放器需要在运行时进行调整,例如 OpenCv,需要调整参数以实现最佳处理。我不能在父类中实现所有子类的所有方法,这对我来说毫无意义。为什么视频需要有调整 OpenCv 参数的方法?
我所需要的只是两者都有“可玩”方法,并且能够将它们存储在 map<string, PlayerPtr> 中。随时访问它们或更改剪辑所持有的播放器。

最佳答案

关键是这种破坏了多态性 - 即使使用 dynamic_cast,您仍然需要检查结果是否不为 0(即检查实际类型),正如您可能已经知道的那样, dynamic_cast 以非常慢而闻名(并且需要在可执行文件中内置 RTTI 信息)。

您是否有任何理由无法将纯虚拟 rewind() 方法添加到您的 Player 界面?然后你只需调用它,继承的类就可以在这种情况下做任何它决定的事情。其他子类可能将其实现为空(或者在 Player 本身中它甚至可以默认为空,以便子类在不需要时不必实现它)。甚至可能还有一些更“通用”的虚函数,如 reset()restart() 等,它们只会为 rewind() 调用 TapePlayer 引擎盖下。

您当然可以更喜欢更复杂的解决方案,例如访问者/观察者(TapePlayerRewindObserver 并观察 rewind 事件)等

编辑:

因此,为了解决编辑评论问题——如果需要调整不同的类型,那么同样,您可以只使用一个虚拟方法 tweak()(纯方法或使用默认的空 impl)并进行任何调整是需要的。否则你最终会得到一长串 if 并根据实际类型调用调整方法。

如果调整需要一些特殊参数,那么情况可能会很困难......一种选择可能是有一个调整参数接口(interface)(并用它调用调整方法),但如果参数不能统一你无论如何都需要在 tweak 方法中进行动态转换以转换为正确的参数类型(这基本上会导致双重分派(dispatch),这在 C++ 中需要在某些时候进行转换)......但无论如何仍然需要在调用站点不太好。

这还取决于您实际需要设置调整参数的时间 - 如果在创建实例时设置所有内容就足够了(并且调整参数之后不会更改),或者是否需要稍后更改它们。如果只需要在启动时设置,那么您可以为不同的对象类型设置工厂类,工厂可以设置参数。

(从技术上讲,您甚至可以用类似的方式处理更改参数的必要性,通过为各种玩家类型保留设置对象类型,玩家也会保留对它们的引用,在创建对象时分配,一旦他们需要更改,您将更改设置并调用 tweak()update() 或类似的函数来通知对象某些设置已更改并需要重新设置-应用)

关于c++ - 如何从返回指向父对象的指针的方法中获取指向子对象的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47673733/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com