简体   繁体   English

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

[英]c++ invalid covariant return type with pointer

I already searched a lot to find a solution for my problem, but I can't find a way to get the following code to work. 我已经进行了大量搜索以找到解决问题的方法,但是我找不到使以下代码正常工作的方法。

Background 背景

I wrote a class structure that represents any kind of Archive (in my real case, this would be a FileRepository which also might be an Archive). 我写了一个表示任何类型的Archive的类结构(在我的实际情况下,这将是FileRepository,也可能是Archive)。 Therefore I defined a pure virtual class structure representing an archive. 因此,我定义了一个代表存档的纯虚拟类结构。

An archive is actually a directory, a directory is actually an entity (Base in this case). 档案实际上是一个目录,目录实际上是一个实体(在这种情况下为Base)。 A file within this archive also would be an entity (Base). 该存档中的文件也将是一个实体(基础)。 These classes are used as interface for real implementations. 这些类用作实际实现的接口。

In the code you'll see the My... implementations of these classes. 在代码中,您将看到这些类的My ...实现。

Problem 问题

The MyDirectory implementation overwrites the Base's getParent method which expects a Directory to be returned. MyDirectory实现覆盖了Base的getParent方法,该方法希望返回目录。 Actually, the MyDirectory implementation only can have a MyDirectory as parent, therefor the new implementation returns a MyDirectory, not a Directory. 实际上,MyDirectory实现只能将MyDirectory作为父级,因此新实现将返回MyDirectory,而不返回Directory。 That's where C++ throws the error message! 这就是C ++抛出错误消息的地方!

The compiler doesn't know, that MyDirectory actually is a Directory, because I overwrite the getParent method in the MyBase class, before declaring the MyDirectory class. 编译器不知道MyDirectory实际上一个目录,因为在声明MyDirectory类之前,我覆盖了MyBase类中的getParent方法。

And as MyDirectory also wants to call specific MyDirectory methods (as getAbsolutePath), I really need the return type to be MyDirectory, not Directory. 而且由于MyDirectory也想调用特定的MyDirectory方法(如getAbsolutePath),因此我确实需要将返回类型设置为MyDirectory,而不是Directory。 (and static_cast did not work, either :() (并且static_cast无效,或者:()

I would be happy about any hint, how to solve my problem :) 我很高兴有任何提示,如何解决我的问题:)

Edit: Details 编辑:详细信息

The problem actually is the complicated inheritance graph. 问题实际上是复杂的继承图。 The problem is that MyDirectory inherits MyBase, but MyBase's method returns MyDirectory - but the Base class requires to return a Directory, but at declaration, c++ does not know that MyDirectory actually is a Directory. 问题是MyDirectory继承了MyBase,但是MyBase的方法返回MyDirectory-但是Base类需要返回Directory,但是在声明时,c ++不知道MyDirectory实际上是Directory。 I'm trying to solve, that MyDirectory can return a MyDirectory instance and does not require to return a Directory instance. 我正在尝试解决,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) {}
};

Covariant return types are just convienience. 协变量返回类型只是方便。

Write GetMyParent() that returns MyDirectory . 编写GetMyParent()返回MyDirectory Defer the implementation of GetParent and GeyMyParent until MyDirectory is visible, then have GetParent call GetMyParent . GetParentGeyMyParent的实现推迟到MyDirectory可见之前,然后让GetParent调用GetMyParent

In MyDirectory you could make GetParent fully covarient if you want to, but I wouldn't bother. 如果需要,在MyDirectory可以使GetParent完全协变,但是我不会打扰。 Never override GetParent after MyBase , if that is needed override GetMyParent instead. 切勿在MyBase之后重写GetParent ,如果需要,请重写GetMyParent

Maybe make GetParent private so you do not accidentally call it. 也许将GetParent私有,这样就不会意外调用它。 If you have a MyBase , call GeyMyParent instead. 如果您有MyBase ,请改为调用GeyMyParent

If this makes code annoying to maintain, write a free function calped GetParent that uses overrides to pick which one to call. 如果这使代码难以维护,请编写一个免费的函数Calped GetParent ,该函数使用重写选择要调用的函数。 If you hate free functions, add a non virtual method that picks which one to call (well two, one in Base and one in MyBase ). 如果您讨厌自由函数,请添加一个非虚拟方法,该方法选择要调用的方法(两种方法,一种在Base ,一种在MyBase )。

The only problem with the free function/non-virtual method is that your multi-path tree can confuse it, resulting in ambiguity. 自由功能/非虚拟方法的唯一问题是您的多路径树可能会混淆它,从而造成歧义。 I would just go with calling GetMyParent() when you know have a MyBase and need a MyDirectory* . 当您知道拥有MyBase并需要MyDirectory*时,我只想调用GetMyParent() The requirements for a ridiculous number of overrides of the method/free function, or the template hackery required to have ti happen automatically, isn't worth it. 对于方法/自由功能的大量替代要求,或者要求ti自动发生的模板黑客行为,是不值得的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM