c ++带指针的无效协变返回类型

时间:2013-02-14 11:43:38

标签: c++ oop g++

我已经搜索过很多东西来找到解决我问题的方法,但我找不到办法让下面的代码工作。

背景

我编写了一个代表任何类型存档的类结构(在我的实际情况中,这将是一个FileRepository,它也可能是一个存档)。因此,我定义了一个表示存档的纯虚拟类结构。

存档实际上是一个目录,一个目录实际上是一个实体(在本例中为Base)。此归档中的文件也是实体(Base)。这些类用作实际实现的接口。

在代码中,您将看到这些类的My ...实现。

问题

MyDirectory实现会覆盖Base的 getParent 方法,该方法需要返回目录。实际上,MyDirectory实现只能将MyDirectory作为父项,因此新实现返回MyDirectory而不是Directory。这就是C ++抛出错误消息的地方!

编译器不知道,MyDirectory实际上 是一个目录,因为我在声明MyDirectory类之前覆盖了MyBase类中的 getParent 方法。

由于MyDirectory也想调用特定的MyDirectory方法(如getAbsolutePath),我真的需要返回类型为MyDirectory,而不是Directory。 (而static_cast也不起作用:()

我会对任何暗示感到高兴,如何解决我的问题:)

修改:详情

问题实际上是复杂的继承图。问题是MyDirectory继承MyBase,但MyBase的方法返回MyDirectory - 但Base类需要返回一个Directory,但是在声明时,c ++不知道MyDirectory实际上是一个Directory。我正在尝试解决,MyDirectory可以返回MyDirectory实例,并且不需要返回Directory实例。

// Just an example code - actually is separated in .h and .cpp and cleaner and and and... :)

class Directory;
class MyDirectory;

class Base {
public:
    /// Returns the parent directory
    virtual Directory *getParent()=0;
};

class Directory : virtual public Base {
public:
};

class Archive : virtual public Directory {
public:
};

// ---------------------------------

class MyBase : virtual public Base {
public:
    /// Constructor
    MyBase(int i, int j, int k) {}

    /// Returns the parent directory
    MyDirectory *getParent() { return NULL; }

    /// Returns the parent directory
    virtual const char *getAbsolutePath() const { return "my full path"; }
};

class MyDirectory : virtual public Directory, public MyBase {
public:
    /// Constructor
    MyDirectory(int i, int j) : MyBase(i, j, i+j) {}

    /// Returns the parent directory (not really, I know! Just an example)
    virtual const char *getAbsolutePath() const { return getParent()->getAbsolutePath(); }
};

class MyArchive : virtual public Archive, public MyDirectory {
public:
    /// Constructor
    MyArchive(int i) : MyDirectory(i, i) {}
};

1 个答案:

答案 0 :(得分:1)

协变回报类型只是方便。

写回GetMyParent()的{​​{1}}。推迟MyDirectoryGetParent的实施,直到GeyMyParent可见,然后MyDirectory致电GetParent

GetMyParent中,如果您愿意,可以让MyDirectory完全协变,但我不会打扰。永远不要在GetParent后覆盖GetParent,如果需要,请改写MyBase

也许将GetMyParent设为私有,这样您就不会不小心打电话给它。如果您有GetParent,请改为呼叫MyBase

如果这会使代码难以维护,请编写一个自由函数calped GeyMyParent,它使用覆盖来选择要调用的函数。如果您讨厌自由函数,请添加一个非虚拟方法来选择要调用的函数(两个,一个在GetParent中,另一个在Base中)。

自由函数/非虚方法的唯一问题是您的多路径树可能会混淆它,导致模糊。如果您知道MyBase并且需要GetMyParent(),我会调用MyBase。对于方法/自由函数的荒谬数量的覆盖或者自动发生的模板hackery的要求是不值得的。