我正在用 C++ 编写一个“文件系统”抽象,具有以下继承层次结构:
[Node]
^
|
+----[Dir]
|
+----[File]
Node
定义了与两者相同的所有行为(名称、上次修改时间等)但是,我有一个名为 getParent() 的
返回类型 Node
方法Dir *
。这很好用,因为虽然 Dir.h
显然需要知道 Node.h
中的实现规范,但 Node.h
不需要了解 Dir.h
中的内容,以便我可以使用前向声明。太好了。
但是,我最近决定添加多重继承,这样我就可以在特定时间支持文件系统的“快照”。这些是“实时”Node
File
和 Dir
类的只读版本,并且由于实时版本可以从写入,我让每个实时版本都继承了它的快照双重:
[NodeSnapshot] <------ [Node]
^ ^
| |
+---[DirSnapshot]<---+---[Dir]
| |
+---[FileSnapshot]<--+---[File]
因此,Dir
继承自Node
和DirSnapshot
,File
继承自FileSnapshot
和 节点
。到目前为止一切看起来都很好,直到我们到达 getParent()
的声明。在 NodeSnapshot
中,我返回一个 DirSnapshot *
。没问题,我可以再次使用前向声明。但是,在 Node
中,我想返回 Dir *
。作为程序员,我知道 Dir
是 DirSnapshot
的子类型,但是编译器无法知道这一点,因为前向声明没有任何有用的信息嵌入其中的信息。
是否可以通知编译器这个前向声明是一个子类,因此它不应该告诉我 Dir::getParent()
的返回类型与 DirSnapshot::getParent()
?
最佳答案
可以在没有任何语言支持的情况下实现/模拟返回类型协变,尽管解决方案往往很冗长。另一方面,相互递归定义是没有问题的。需要使用调用虚拟私有(private)函数的非虚拟公共(public)(内联)函数。这是一种有用的技术,有些人甚至认为所有接口(interface)都应该这样实现。
这是一个例子:
// forward declare classes
class A;
class B;
class AA;
class BB;
// parents
class A
{
virtual B* getB_impl();
public:
B* getB() { return getB_impl(); }
};
class B
{
virtual A* getA_impl();
public:
A* getA() { return getA_impl(); }
};
// kids
class AA : public A
{
virtual BB* getBB_impl();
B* getB_impl();
public:
BB* getB() { return getBB_impl(); }
};
class BB : public B
{
virtual AA* getAA_impl();
A* getA_impl();
public:
AA* getA() { return getAA_impl(); }
};
// implement parents
B* A::getB_impl() { return new B; }
A* B::getA_impl() { return new A; }
// implement kids
B* AA::getB_impl() { return getBB_impl(); }
BB* AA::getBB_impl() { return new BB; }
A* BB::getA_impl() { return getAA_impl(); }
AA* BB::getAA_impl() { return new AA; }
// check
A a; B b;
A* pa; B* pb;
AA aa; BB bb;
AA* paa; BB* pbb;
pa = b.getA();
pb = a.getB();
pa = bb.getA();
pb = aa.getB();
paa = bb.getA();
pbb = aa.getB();
关于c++ - 在 C++ 中用不完整的派生类覆盖方法返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13968220/