在c ++中限制对纯虚函数的派生类的访问

时间:2013-09-23 13:16:12

标签: c++ virtual

class A
{    
public:
    void virtual magic() = 0;
    void bar()
    {
        magic();    // this should be legal
    }        
};

class B: public A
{    
public:
    void magic()
    {
        cout<<"implement magic here"<<endl;
    }
};

class C: public B
{
     void foo()
     {
         magic();     // this should not be allowed, i.e. create compile-time error
     }
};

因此A的纯虚拟基类B可以访问magic(),但不能访问C的任何派生类B。这可以使用访问说明符和/或朋友声明或以任何其他方式实现吗?

4 个答案:

答案 0 :(得分:7)

基本上,您无法降低虚拟方法的可见性。一旦它在A中公开,就没有任何方法可以在任何派生类中使其受到保护或私有。

答案 1 :(得分:4)

如果您有class A的访问权限,请将magic的访问权限更改为private

private:
         void virtual magic() = 0;

然后让B班成为A班的朋友:

class A
{
    friend class B;

答案 2 :(得分:2)

使用所谓的模板方法模式,你真正想要的最有可能是separate the public interface from the implementation detail of inheritance

您的公共接口应使用非虚方法。虚拟方法应该都是私有的。然后基类中的接口可以强制执行不变量并进行样板工作。派生类仍然可以覆盖虚拟方法,它们无法直接调用它。

仅当派生类需要调用虚方法的基本实现时,才能使虚方法受到保护。这几乎都是。

基类析构函数应该是public和virtual,或者是protected和nonvirtual。前者当您希望使用基类接口执行销毁时。 现在这就是全部:)

具体地:

#include <iostream>
#include <cassert>
using namespace std;

class A
{
    // we do magic without sprinking any dust, but optionally we could sprinkle some beforehand
    void virtual sprinkle() {};
    void virtual magic(int) = 0;
public:
    void doSomeMagic(int power) {
        assert(power > 3 and power < 8);
        sprinkle();
        magic(power);
    }
    virtual ~A() {}
};

class B: public A
{
    void magic(int power) {
        cout << "B: did magic of with power=" << power << endl;
    }

};

class C : public B
{
    void sprinkle() {
        cout << "C: also sprinked some dust before doing the magic" << endl;
    }
};

int main()
{
    B b;
    C c;
    b.doSomeMagic(5);
    c.doSomeMagic(6);
    return 0;
}
B: did magic of with power=5 
C: also sprinked some dust before doing the magic
B: did magic of with power=6

答案 3 :(得分:0)

正如Dave S的评论所示,更改C :: magic()的访问说明符:

class A
{

    public:
         void virtual magic() = 0;
};

class B: public A
{

    public:
        void magic()
         {
           cout<<"implement magic here"<<endl;
         }
};

class C:public B
{
private:
    void virtual magic(){};
};