举例class CRoot
{
    int m_iOnlyRoot;
protected:
    int m_iRootAndDerived;
public:
    int m_iEvery;
    CRoot()
    {
        m_iOnlyRoot=0;
    }
/* 如何声明一个变量或者函数能让 CParent 访问, 而不能让从 CParent 再继承的类不能访问? */
};class CParent : public CRoot
{
public:
    CParent()
    {
        m_iRootAndDerived=0;
        m_iEvery=0;
    }
};class CChild : public CParent
{
public:
    CChild()
    {
        m_iRootAndDerived=1;
    }
};问题是这样的,CRoot里面的3个不同权限的变量大家都很清楚,现在如何在 CRoot 里面生命一个变量或者方法只能被几代子类访问,再下面的就不能访问了?
这个很有实用意义,比如说我对外发布一个类,这个类可以访问父类的方法,比如说是一些重要数据,从发布出去的类之上的类访问这些数据都是有安全保障的,从这个发布出去的类再继承的类就不能访问修改这些重要数据,用以保证用户误操作导致的数据损坏.

解决方案 »

  1.   

    代码里面的注释写错了,应该是
    /* 如何声明一个变量或者函数能让 CParent 访问, 而不能让从 CChild 再继承的类不能访问? */
      

  2.   

    private 类型只能本类自己用
    portected 类型只要是派生类都能访问
    public 更别说了
      

  3.   

    将代码修改如下,注意红色的部分:class CRoot
    {
    private:
        int m_iOnlyRoot;
    protected:
        int m_iRootAndDerived;
    public:
        int m_iEvery;
        CRoot()
        {
            m_iOnlyRoot=1;
    m_iRootAndDerived=2;
    m_iEvery=3;
        }
    void Show()
    {
    printf("m_iOnlyRoot:%d,m_iRootAndDerived:%d,m_iEvery:%d\n",m_iOnlyRoot,m_iRootAndDerived,m_iEvery);
    }
    /* 如何声明一个变量或者函数能让 CParent 访问, 而不能让从 CParent 再继承的类不能访问? */
    };class CParent : public CRoot
    {
    private:
    int m_iRootAndDerived;

    public:
        CParent()
        {
    m_iRootAndDerived=CRoot::m_iRootAndDerived;
        }
    void Show()
    {
    printf("m_iRootAndDerived:%d,m_iEvery:%d\n",m_iRootAndDerived,m_iEvery);
    }
    };class CChild : public CParent
    {
    public:
        CChild()
        {
        }
    void Show()
    {
    printf("m_iEvery:%d\n",m_iEvery);
    }
    };
      

  4.   

    在代码块里无法标志颜色,修改的代码为:
    private:
    int m_iRootAndDerived;
    public:
        CParent()
        {
    m_iRootAndDerived=CRoot::m_iRootAndDerived;
        }
      

  5.   

    楼上的你行不行啊,你这样做是声明了2个m_iRootAndDerived,而且再派生出来的类使用CRoot::m_iRootAndDerived一样可以访问到Root的m_iRootAndDerived.我要的是针对Root里面声明的变量/函数,在子类的子类里面不能被访问
      

  6.   

    我在把问题说的更明白一点吧.类A有变量var,类B从A派生能访问类A的var,类C从B派生如何禁止类C访问类A的var?
      

  7.   

    A是基类,B 私有继承A
    C继承B,则A的什么东西都不能被C直接使用
      

  8.   

    B如果私有继承则A里面的所有东西外面都不能访问,我不是想全面封杀A,只是A其中的某个或某几个变量/函数被禁止访问.
      

  9.   

    私有加friend
    class CRoot
    {
    int m_iRootAndDerived;
    int m_iOnlyRoot;
    friend class CParent;
    protected:

    public:
    int m_iEvery;
    CRoot()
    {
    m_iOnlyRoot=0;
    }
    /* 如何声明一个变量或者函数能让 CParent 访问, 而不能让从 CParent 再继承的类不能访问? */
    };class CParent : public CRoot
    {
    public:
    CParent()
    {
    m_iRootAndDerived=0;
    m_iEvery=0;
    }
    };class CChild : public CParent
    {
    public:
    CChild()
    {
    m_iRootAndDerived=1;  //编译报错,无法访问:cannot access private member declared in class 'CRoot' }
    };
      

  10.   


    我现在就是用的这个方法,但是Root派生出来10多个类,只有其中两三个对外可以使用,要把10多个都加为friend也太说不去了吧,而且内部的结构也完全破坏了面向对象的机制阿
      

  11.   

    我原来也是这样想到。现在看来,静态的办法是无法实现了,采用动态THUNK吧,即在子类的构造函数里强行把父类的PUBLIC或PROTECTED变量改为PRIVATE,以此子类作为基类派生的类在运行时就不能访问这些变量了(不过设计时和编译时均可通过)。
      

  12.   

    初步感觉:职责不清。应该是CRoot负责控制其子类CParent的权限,而不负责控制其子类的子类CChild的权限。CChild的权限应该由其父类CParent控制。
      

  13.   


    所以在CParent使用using语句更改变量属性。
    class CRoot
    {
    private:
        int m_iOnlyRoot;
    protected:
        int m_iRootAndDerived;
    public:
        int m_iEvery;
        CRoot()
        {
            m_iOnlyRoot=0;
        }
    /* 如何声明一个变量或者函数能让 CParent 访问, 而不能让从 CParent 再继承的类不能访问? */
    };class CParent : public CRoot
    {
    private:
    using CRoot::m_iRootAndDerived;//变为私有,CChild就不能访问了。
    public:
        CParent()
        {
            m_iRootAndDerived=0;
            m_iEvery=0;
        }
    };class CChild : public CParent
    {
    public:
        CChild()
        {
            m_iRootAndDerived=1;
    m_iEvery=0;
        }
    };
    int main() 

    CRoot a;
    CParent b;
    CChild c; return 0;

      

  14.   

    对于函数,雷同。private:
    using CRoot::func;
      

  15.   


    谢谢 hityct1 的恢复,已经很接近了,但是这个方法还是有漏洞
    class CChild : public CParent
    {
    public:
        CChild()
        {
            CRoot::m_iRootAndDerived=100; // 注意这里, CChild 直接绕过了 CParent 的限制, 还是达到了访问 CRoot 变量的目的
            m_iEvery=0;
        }
    };CChild 也是 CRoot 的派生类,它也能访问 CRoot 的 protected 的东西, CParent 虽然限制了默认使用方法,但是CChild可以用上面的方法绕过限制还是能够访问到 CRoot 的变量.
    我现在需要的是在 CParent 里面有没有什么方法对 CRoot 的变量/函数访问的权限进行截止,在CParent之前的派生都可以访问,从CParent之后就都不能访问?
      

  16.   


    个人认为hityct1的回答已经很好了:
    首先,LZ的要求上确实有“职责不清”的感觉,爸爸管儿子,爷爷还是别管孙子了比较好,毕竟爷爷管的再怎么严,爸爸开后门,孩子想溜,爷爷也没办法。
    其次,能否访问只是编译器的职责,实际上不管如何限制,只要计算出偏移量,那么无论是谁都可以访问被限制的变量。
    另外,我们做限制的目的,仅仅是希望其他开发人员使用我们设计的类时,不要乱搞男女关系,免得出问题了都不知道问题在哪里。所以我们限制了他们直接使用m_iRootAndDerived = 100的权利,并且使用了using明确地警告他们不要访问它,但是如果他们非要使用CRoot::m_iRootAndDerived去访问,那么这在本质上与他们计算出偏移量再访问是一样的,这种后果应该让他们自己承担。
      

  17.   

    不使用继承可否?class CRoot
    {
    private:
        int m_iOnlyRoot;
        int m_iRootAndDerived;
        int m_iEvery;
    public:
        CRoot()
        {
    m_iRootAndDerived = 666;
            m_iOnlyRoot=0;
        }
    int& GetRootAndDerived()
    {
    return m_iRootAndDerived;
    } int& GetEvery()
    {
    return m_iEvery;
    } void printRootAndDerived()
    {
    cout<<m_iRootAndDerived<<endl;
    }
    /* 如何声明一个变量或者函数能让 CParent 访问, 而不能让从 CParent 再继承的类不能访问? */
    };class CParent
    {
    private:
    CRoot m_root;
    public:
        CParent()
        {
            m_root.GetRootAndDerived() = 10;
            m_root.GetEvery() = 0;
        } int& GetEvery()
    {
    return m_root.GetEvery();
    } void printRootAndDerived()
    {
    m_root.printRootAndDerived();
    }
    };class CChild : public CParent
    {
    public:
        CChild()
        {
    //CRoot::m_iRootAndDerived=1;
    GetEvery() = 0;
        }
    };CParent写起来繁琐一些。
    一个可能的影响是由于不是继承关系,不能使用多态。
      

  18.   

    是啊。
    即使像多态,我们也可绕过的。
    CChild c;
    CParent* p = &c;
    p->CParent::fun();
      

  19.   

    定义类CParent时通过私有派生:
    class CParent:private CRoot{
    ......
    };另外,我理解定义CRoot时如果知道只有哪些类需要访问其成员,那么就可以声明这些类为友员,并没破坏封装性。