3

所以这可能是一个奇怪的问题,但我有充分的理由问这个问题。

我的问题的要点是,给出一个在类层次结构上有两个派生级别的示例:

主要基类:

class Animal
{
  virtual void Draw() = 0;
};

派生类:

class Dog : public Animal
{
  virtual void Draw()
  {
    // draw a generic dog icon or something...
  }
};

进一步推导:

class Corgi : public Dog
{
  virtual void Draw()
  {
    // draw a corgi icon...
  }
};

现在,我希望能够从Corgi类中永久地将“this”指针向下转换为Dog指针,然后将其作为 Animal 传递到其他地方。然后这个其他地方将能够调用Draw函数并获取Dog方法,而不是虚拟Corgi方法。我知道这很奇怪,但同样,我有一个模糊的正当理由想要这样做。

我已经尝试了所有不同的铸造操作员并且没有任何运气,但也许有一种一致的方法可以解决这个问题?过去,我因未正确使用而给自己造成了麻烦,dynamic_cast这导致指针的类似状态。也许这一次我可以利用它来发挥我的优势?

编辑: 也许上面的例子并没有清楚地说明我想要达到的目标,所以我会详细说明我的真正目标。

我正在尝试实现注册基类实现的简写,这些实现链接到我已经使用了一段时间的脚本系统。脚本系统依赖于一个基类IScriptContext方便访问真实代码函数和成员变量访问。基类在内部注册它们的成员函数地址和成员变量地址,稍后通过查找表分派/访问这些地址。我正在为脚本系统添加对类派生层次结构的适当支持,我认为能够隔离这些接口的基类版本将有助于节省时间并使整个过程对我来说更清晰使用脚本解释器注册可用的基类。还有其他方法可以实现这一点,例如为每个可用基类的每个所需方法注册类特定函数指针(例如this->Dog::CallFunctionthis->Dog::SetMemberthis->Dog::GetMember.) 但是,如果我需要的话,我认为使用界面可以让我在以后更轻松地修改事情。

我希望所有这些都有意义。

谢谢!

4

4 回答 4

6

你有一个Corgi对象。你可以:

  1. 通过对所有调用Dog使用限定符(例如) ,将其视为无处不在的对象。这会失去您的虚拟调度,并且几乎可以肯定这不是您从问题的阅读方式中想要的。Dog::ptr->Dog::draw();

  2. 实际上Dog从您的Corgi. 只需使用普通类型执行此操作,static_cast因为您将转换任何其他类型或让隐式转换接管(例如Corgi c; Dog d(c);)。

这些是您可以使用的选项。想要保留 aCorgi但在任何地方都自动假装它是 aDog既不合理也不合法,因此语言没有提供它。

于 2012-12-28T22:00:10.210 回答
2

让我先说你的设计看起来有问题。

但是,您可以明确说明要调用层次结构中的哪个函数:

Corgi* corgi = new Corgi;
corgi->Dog::draw();

这将调用draw方法 from Dog,而不是 from Corgi。(我希望我能正确理解你的要求)。

于 2012-12-28T21:59:03.547 回答
2

Tomalak已经概述了您可以使用的两个主要选择:

  • 使用合格的电话,或

  • 构造 aDog作为Dog您的Corgi.

除了这些,你还可以

  • 使用简单的包装器

例如

class LooksLikeDog
    : public Dog
{
private:
    Dog*  realObject_;

    LooksLikeDog( LooksLikeDog const& );                    // No such.
    LooksLikeDog& operator=( LooksLikeDog const& );         // No such.

public:
    LooksLikeDog( Dog& other )
        : realObject_( &other )
    {}

    // Just for exposition: not implementing this does the same.
    virtual void draw() override { Dog::draw(); }

    // Example of other method that may need to be implemented:
    virtual void bark() override { realObject_->bark(); }
};

但最好的解决方案很可能是修复您的设计。;-)

于 2012-12-28T22:26:55.137 回答
0

实现 Corgi 绘图功能并调用您父级的实现:

virtual void Corgi::Draw() 
{ 
    Dog::draw(); 
}
于 2012-12-28T23:02:05.260 回答