我已经进行了大量搜索以找到解决问题的方法,但是我找不到使以下代码正常工作的方法。
背景
我写了一个表示任何类型的Archive的类结构(在我的实际情况下,这将是FileRepository,也可能是Archive)。因此,我定义了代表文件的纯虚拟类结构。
文件实际上是一个目录,目录实际上是一个实体(在这种情况下为Base)。该存档中的文件也将是一个实体(基础)。这些类用作实际实现的接口(interface)。
在代码中,您将看到这些类的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) {}
};
最佳答案
协变量返回类型只是方便。
编写返回GetMyParent()
的MyDirectory
。推迟GetParent
和GeyMyParent
的实现,直到MyDirectory
可见,然后让GetParent
调用GetMyParent
。
如果需要,可以在MyDirectory
中使GetParent
完全协变,但是我不会打扰。切勿在GetParent
之后覆盖MyBase
,如果需要,请改写GetMyParent
。
也许将GetParent
设为私有(private),这样就不会意外地调用它。如果您有MyBase
,请改为调用GeyMyParent
。
如果这使代码难以维护,请编写一个免费函数calct GetParent
,该代码使用替代来选择要调用的代码。如果您讨厌自由函数,请添加一个非虚拟方法,该方法选择要调用的方法(两种,一种在Base
中,一种在MyBase
中)。
自由功能/非虚拟方法的唯一问题是您的多路径树可能会使其混淆,从而造成歧义。当您知道有GetMyParent()
且需要MyBase
时,我只想调用MyDirectory*
即可。对于方法/自由功能的大量替代要求,或者要求ti自动发生的模板黑客行为,是不值得的。