举例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 里面生命一个变量或者方法只能被几代子类访问,再下面的就不能访问了?
这个很有实用意义,比如说我对外发布一个类,这个类可以访问父类的方法,比如说是一些重要数据,从发布出去的类之上的类访问这些数据都是有安全保障的,从这个发布出去的类再继承的类就不能访问修改这些重要数据,用以保证用户误操作导致的数据损坏.
{
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 里面生命一个变量或者方法只能被几代子类访问,再下面的就不能访问了?
这个很有实用意义,比如说我对外发布一个类,这个类可以访问父类的方法,比如说是一些重要数据,从发布出去的类之上的类访问这些数据都是有安全保障的,从这个发布出去的类再继承的类就不能访问修改这些重要数据,用以保证用户误操作导致的数据损坏.
/* 如何声明一个变量或者函数能让 CParent 访问, 而不能让从 CChild 再继承的类不能访问? */
portected 类型只要是派生类都能访问
public 更别说了
{
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);
}
};
private:
int m_iRootAndDerived;
public:
CParent()
{
m_iRootAndDerived=CRoot::m_iRootAndDerived;
}
C继承B,则A的什么东西都不能被C直接使用
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' }
};
我现在就是用的这个方法,但是Root派生出来10多个类,只有其中两三个对外可以使用,要把10多个都加为friend也太说不去了吧,而且内部的结构也完全破坏了面向对象的机制阿
所以在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;
}
using CRoot::func;
谢谢 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之后就都不能访问?
个人认为hityct1的回答已经很好了:
首先,LZ的要求上确实有“职责不清”的感觉,爸爸管儿子,爷爷还是别管孙子了比较好,毕竟爷爷管的再怎么严,爸爸开后门,孩子想溜,爷爷也没办法。
其次,能否访问只是编译器的职责,实际上不管如何限制,只要计算出偏移量,那么无论是谁都可以访问被限制的变量。
另外,我们做限制的目的,仅仅是希望其他开发人员使用我们设计的类时,不要乱搞男女关系,免得出问题了都不知道问题在哪里。所以我们限制了他们直接使用m_iRootAndDerived = 100的权利,并且使用了using明确地警告他们不要访问它,但是如果他们非要使用CRoot::m_iRootAndDerived去访问,那么这在本质上与他们计算出偏移量再访问是一样的,这种后果应该让他们自己承担。
{
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写起来繁琐一些。
一个可能的影响是由于不是继承关系,不能使用多态。
即使像多态,我们也可绕过的。
CChild c;
CParent* p = &c;
p->CParent::fun();
class CParent:private CRoot{
......
};另外,我理解定义CRoot时如果知道只有哪些类需要访问其成员,那么就可以声明这些类为友员,并没破坏封装性。