就像我每次尝试混合泛型编程和多态时一样,我不得不为我的编译器而烦恼。 C ++很有趣,但有多困难(好吧,我的大脑也很复杂,没有用)。
我在下面写了一个简化但类似的情况,我得到相同的编译器错误:
template<typename Object>
class Environment;
class Boat {
};
template<typename Object>
class Worker {
public:
typedef Object Object_type;
public:
Worker() {}
virtual ~Worker() throw() {}
virtual bool work() = 0;
virtual const Environment<Object>*
env() const=0;
};
template<typename Object>
class Environment {
public:
typedef Object Object_type;
public:
Environment() {}
virtual ~Environment() throw() {}
virtual Worker<Object>*
spawnWorker() const=0;
};
template<typename Employee>
class Enterprise;
template<typename Object>
class Painter: public Worker<Object> {
public:
using typename Worker<Object>::Object_type;
typedef Enterprise<Painter<Object_type> >
Environment_type;
public:
Painter( const Environment_type *env) : enterprise(env){}
const Environment_type*
env() const override {return enterprise; }
bool work() override {return true;}
private:
const Environment_type* const
enterprise;
};
template<typename Employee>
class Enterprise: public Environment<typename Employee::Object_type> {
public:
using typename Environment<typename Employee::Object_type>::Object_type;
public:
Enterprise() {}
~Enterprise() throw() {}
Worker<Object_type>*
spawnWorker() const override { return new Painter<Object_type>(this); }
};
int main() {
Enterprise< Painter<Boat> > enterprise;
auto painter=enterprise.spawnWorker();
painter->work();
delete painter;
return 0;
}
g ++给出错误:
test.cpp: In instantiation of ‘class Painter<Boat>’:
test.cpp:50:7: required from ‘class Enterprise<Painter<Boat> >’
test.cpp:61:33: required from here
test.cpp:42:25: error: invalid covariant return type for ‘const Environment_type* Painter<Object>::env() const [with Object = Boat; Painter<Object>::Environment_type = Enterprise<Painter<Boat> >; typename Worker<Object>::Object_type = Boat]’
env() const override {return enterprise; }
^
test.cpp:16:25: error: overriding ‘const Environment<Object>* Worker<Object>::env() const [with Object = Boat]’
env() const=0;`
和clang ++可能更容易理解:
test.cpp:42:25: error: return type of virtual function 'env' is not covariant with the return type of the function it overrides ('const Environment_type *' (aka 'const Enterprise<Painter<Object_type> > *') is not derived from 'const Environment<Boat> *')
env() const override {return enterprise; }
^
test.cpp:50:47: note: in instantiation of template class 'Painter<Boat>' requested here
class Enterprise: public Environment<typename Employee::Object_type> {
^
test.cpp:61:33: note: in instantiation of template class 'Enterprise<Painter<Boat> >' requested here
Enterprise< Painter<Boat> > enterprise;
^
test.cpp:16:25: note: overridden virtual function is here
env() const=0;
^
如何解决此问题?如果解决方案仍然存在会更好:
答案 0 :(得分:0)
正如评论中所提到的,问题是派生类试图覆盖具有不同返回类型的函数。您可以通过替换Environment_type
中的Painter
定义来解决此问题:
typedef Environment<Object> Environment_type;
这个修复是否对你的想法有意义,我无法说清楚,但我想这会给你这个想法。
但总的来说设计看起来有点奇怪。这是我的核心问题:
您真的希望Worker
成为继承树的根并将其用于运行时多态吗?我问,因为你无法混合使用Worker<boat>
和Worker<house>
的指针。它们是完全不同的东西,它们的虚函数不匹配。
如果确实想要使用运行时多态性,我建议使用非模板基类。例如,一个船舶绘画企业然后只会产生指向通用工人的指针,而不是船画家。如果你需要它来真正产生一个船画家,那么我会说继承(在这种情况下对于企业/环境)是不你想要的。
如果确实需要基类(但不是运行时多态),您可能需要查看CRTP。它看起来很奇怪,可能会引发更多问题,但它是一个强大的工具,并提供另一层编译时多态性。
如果您需要某个接口,但不一定是继承链,您可能还需要查看类型擦除。