我正在用C ++编写程序,我来自Java,我遇到了一些麻烦。 我想有一个基本抽象类(一个java接口),它定义了派生类必须实现的一些方法。这个方法可以将派生类型作为参数,但在这里我发现了一个问题。如果我使用基类将它们定义为基类中的参数,则编译器不会将派生类型的重新定义视为覆盖,派生类仍然是纯虚拟的。 解决这种情况的正确方法是什么? 谢谢!
答案 0 :(得分:3)
我想你想写这样的东西:
template<class T>
class Interface {
virtual void Method(T i) = 0;
};
class Implement : public Interface<Implement> {
virtual void Method(Implement i) override {
}
};
这称为CRTP。
答案 1 :(得分:0)
这里你应该做的是在派生类中创建一个以基类为参数的函数。您可以使用dynamic_cast
来确保运行时类型确实是派生类(否则抛出异常)。正如克里斯在评论中提到的那样,反变数就是&#34;很难&#34;。
class Base
{
public:
virtual void fn(const Base &base)=0;
}
class Derived:public Base
{
void fn(const Base &base)
{
const Derived *derived=dynamic_cast<const Derived *>(&base);
if(derived!=nullptr)
{//code for derived..
}
}
}
如果你真的必须拥有你所要求的,你应该去CRTP。我怀疑你真的不需要。如果你真的需要它,阿德里安的答案就是你正在寻找的。 p>
请记住,如果您选择CRTP,您将失去继承的一些好处。例如,您无法创建基类指针列表(vector <Base *>
)。每当您使用Base类(Base<Derived>
)时,您都需要选择派生类,这可能会破坏目的。
答案 2 :(得分:0)
你要做的事情也不适用于Java。在Java中,返回类型可以是协变的,但不是方法的参数。如果考虑Liskov原则,那实际上是有意义的:如果缩小派生类的合约,则无法用派生对象替换基础对象。
解决方案可能需要在设计层面上。只是猜测,但是这种问题与您希望在类上以及参数类型上发送调度的情况有关。如果是这种情况,请查看Visitor pattern.