C++ 使用差异访问规范c+覆盖+;

C++ 使用差异访问规范c+覆盖+;,c++,C++,我在参加iKM考试时遇到了一个问题。有一个基类,它有两个带有私有访问说明符的抽象方法。有一个派生类正在重写这些抽象方法,但具有受保护/公共访问说明符 我从未遇到过派生类中重写的方法具有不同访问规范的情况。允许这样做吗?如果是,它是否符合基础和派生(即安全可替代)之间的“是”关系 你能给我指一些参考资料吗?这些资料可以提供关于类的这种用法的更多细节 谢谢。是的,只要签名相同,这是允许的。在我看来,是的,你是正确的,超越了能见度(例如,公共>私有)中断IS-A。我相信Scott Myers有效C++

我在参加iKM考试时遇到了一个问题。有一个基类,它有两个带有私有访问说明符的抽象方法。有一个派生类正在重写这些抽象方法,但具有受保护/公共访问说明符

我从未遇到过派生类中重写的方法具有不同访问规范的情况。允许这样做吗?如果是,它是否符合基础和派生(即安全可替代)之间的“是”关系

你能给我指一些参考资料吗?这些资料可以提供关于类的这种用法的更多细节


谢谢。

是的,只要签名相同,这是允许的。在我看来,是的,你是正确的,超越了能见度(例如,公共>私有)中断IS-A。我相信Scott Myers有效C++系列有一个关于这个问题的讨论。

允许,在两个方向(即从代码>私下<代码> >代码>公共< /代码>,从<代码>公共<代码> >代码>私下<代码> >

另一方面,我认为这不会破坏IS-A关系。我的论点基于两个事实:

  • 使用
    Base&
    (或
    Base*
    )句柄,可以获得与以前完全相同的界面
  • 您完全可以(如果愿意的话)引入一个向前的方法,即
    public
    ,并直接调用
    private
    方法:与更多的输入相同

  • 是的,这是合法的,可访问性是静态检查的(不是动态检查的):

    现在,你为什么要这么做?仅当您直接使用派生类
    B
    (f()的第二个参数)而不是通过基
    A
    接口(f()的第一个参数)使用时,它才起作用。
    如果你总是使用抽象的
    A
    接口(我通常会推荐),它仍然符合“IS-A”关系。

    正如许多人指出的那样,它是合法的

    然而,“IS-A”部分并不是那么简单。当涉及到“动态多态性”时,“IS-A”关系成立,也就是说,你可以用Super做的所有事情,你也可以用派生实例做

    <>但是,在C++中,我们也有一些经常被称为静态多态性的东西(模板,大多数时候)。考虑下面的例子:

    class A {
    public:
        virtual int m() {
            return 1;
        }
    };
    
    class B : public A {
    private:
        virtual int m() {
            return 2;
        }
    };
    
    template<typename T>
    int fun(T* obj) {
        return obj->m();
    }
    
    A类{
    公众:
    虚拟整数m(){
    返回1;
    }
    };
    B类:公共A{
    私人:
    虚拟整数m(){
    返回2;
    }
    };
    模板
    int fun(T*obj){
    返回obj->m();
    }
    
    现在,当您尝试使用“动态多态性”时,一切似乎都正常:

    A* a = new A();
    B* b = new B();
    
    // dynamic polymorphism
    std::cout << a->m(); // ok
    std::cout << dynamic_cast<A*>(b)->m(); // ok - B instance conforms A interface
    // std::cout << b->m(); fails to compile due to overriden visibility - expected since technically does not violate IS-A relationship
    
    A*A=newa();
    B*B=新的B();
    //动态多态性
    std::cout m();//好啊
    std::cout m();//ok-B实例符合一个接口
    //std::cout m();由于覆盖的可见性而无法编译-由于技术上不违反IS-A关系,因此应为
    
    。。。但当您使用“静态多态性”时,您可以说“IS-A”关系不再成立:

    A* a = new A();
    B* b = new B();
    
    // static polymorphism
    std::cout << fun(a); // ok
    //std::cout << fun(b); // fails to compile - B instance does not conform A interface at compile time
    
    A*A=newa();
    B*B=新的B();
    //静态多态性
    std::难道我不认为它打破了is-a,但如果不买这本书,我就不知道了。斯科特·梅耶斯可能是,但他很少上网。
    
    A* a = new A();
    B* b = new B();
    
    // static polymorphism
    std::cout << fun(a); // ok
    //std::cout << fun(b); // fails to compile - B instance does not conform A interface at compile time