PC Lint在派生类中重写方法时会发出警告,该派生类的访问说明符不是继承的访问说明符。例如
class B {
public:
virtual void fubar(void);
};
class D : public B {
private:
virtual void fubar(void);
};
我看到的一个解释是,上面的内容违反了Liskov替换原则,但这是派生类具有更严格访问权限的唯一情况(就像上面的例子一样(,对吧?我还注意到,这里有一个通往D::fubar的后门,因为我们可以将一个指向D的引用/指针强制转换为指向B的引用/指示器,然后我们可以调用D::fubar,因为它是虚拟的。还有其他问题吗?
如果派生类的访问权限较宽松,该怎么办?例如:
class B {
protected:
virtual void fubar(void);
};
class D : public B {
public:
virtual void fubar(void);
};
是否存在与这种类型的覆盖相关的任何问题?
更改访问类型本身没有什么问题。语言允许。只是更改它很可能是一个错误,因为基类设计器已经决定了该方法应该具有什么访问权限。
如果你让它更严格,那真的没关系,因为任何指向基类的指针都可以调用它,所以这个几乎总是一个错误。
如果你不那么严格,它可能会暴露出设计问题,所以这也应该被认为是一个可能的错误。
一个可能的用例是,如果您不拥有基类(即,它是一个外部库或其他什么(。您可以使用它来直接公开某些功能,但同样,应该谨慎对待。
关于您的";后门;请注意,访问说明符是指"访问";正确的";使用语言和诊断错误,而不是恶意使用。有一些想法是,总是把受保护的方法当作公共的(甚至根本不使用受保护的(,因为它们可以随时发布。。。。
最后,请注意,覆盖与访问类型无关。您可以执行以下操作,它将按预期工作:
struct Base {
private:
virtual void foo() = 0;
};
struct Derived: public Base {
private:
void foo() override;
};
编译器资源管理器
在这个代码段中,只有Base
函数可以调用foo()
,但它们将调用Derived
中的overriden函数。注意,由于是私有的,派生实现不能调用Base::foo()
,因此它是一种通常与纯虚拟函数一起使用的模式。