5

考虑以下代码:

class Base
{
public:
    virtual void Foo() {}
};

class Derived : public Base
{
private:
    void Foo() {}
};

void func()
{
    Base* a = new Derived;
    a->Foo(); //fine, calls Derived::Foo()

    Derived* b = new Derived;
//  b->Foo(); //error
    static_cast<Base*>(b)->Foo(); //fine, calls Derived::Foo()
}

关于这个问题,我听到了两种不同的思想流派:

1) 让可访问性与基类相同,因为用户无论如何都可以使用 static_cast 来获得访问权限。

2) 使函数尽可能私有。如果用户需要 a->Foo() 而不是 b->Foo(),那么 Derived::Foo 应该是私有的。如果需要,它总是可以公开的。

有理由选择其中一个吗?

4

3 回答 3

6

限制对子类型中成员的访问会破坏Liskov 替换原则SOLID中的 L )。我一般会建议反对它。

更新:它可能“工作”,因为代码编译并运行并产生预期的输出,但如果您隐藏一个成员,您的意图可能是使子类型不如原始子类型通用。这是违反原则的。相反,如果您的意图是通过只保留 API 用户感兴趣的内容来清理子类型接​​口,请继续执行此操作。

于 2012-04-27T06:43:58.207 回答
3

不是您最初问题的答案,但如果我们谈论的是类设计......

正如 Alexandrescu 和 Sutter 在他们的第 39 条规则中建议的那样您应该更喜欢使用公共的非虚拟函数和私有/受保护的虚拟函数:

class Base {
public:
    void Foo(); // fixed API function

private:
    virtual void FooImpl(); // implementation details
};

class Derived {
private:
    virtual void FooImpl(); // special implementation
};
于 2012-04-27T08:24:27.323 回答
1

这取决于您的设计,是否要使用virtual派生类对象访问该函数。
如果不是,那么是的,最好制作它们privateprotected.

没有基于访问说明符的代码执行差异,但代码变得更干净。
一旦你限制了类virtual函数的访问;读者class可以确定 this 不会被派生类的任何对象或指针调用。

于 2012-04-27T06:42:57.797 回答