我最近不得不这样做,我不喜欢这些解决方案让类类型在当前命名空间中徘徊而没有任何目的的方式。如果您真的只是希望此功能可用于单个类,那么我将使用与上述不同的模式。
class Safety {
protected:
std::string _Text="";
public:
Safety(const std::string& initial_text) {
_Text=initial_text;
}
void Print(const std::string& test) {
std::cout<<test<<" Value: "<<_Text<<std::endl;
}
};
class SafetyManager {
protected:
// Use a nested class to provide any additional functionality to
// Safety that you want with protected level access. By declaring
// it here this code only belongs to this class. Also, this method
// doesn't require Safety to inherit from anything so you're only
// adding weight for the functionality you need when you need it.
// You need to be careful about how this class handles this object
// since it is really a Safety cast to a _Safety. You can't really
// add member data to this class but static data is ok.
class _Safety : Safety {
public:
void SetSafetyText(const std::string& new_text) {
_Text=std::string(new_text);
}
};
public:
static void SetSafetyText(Safety* obj, const std::string& new_text) {
if(obj==nullptr) throw "Bad pointer.";
_Safety& iobj=*(_Safety*)obj;
iobj.SetSafetyText(new_text);
}
};
然后在 main (或其他任何地方)中,您无法通过 Safety 修改 _Text 但您可以通过 SafetyManager (或其后代)。
#include "Safety.h"
int main() {
Safety t("Hello World!");
t.Print("Initial");
SafetyManager::SetSafetyText(&t, "Brave New World!");
t.Print("Modified");
/*
t._Text; // not accessible
Safety::SetSafetyText(&t, "ERR");// doesn't exist
t.SetSafetyText(&t, "ERR"); // doesn't exist
_Safety _safety; // not accessible
SafetyManager::_Safety _safety; // not accessible
*/
}
有人会说这比友元类遵循更好的 OOP 实践,因为它更好地封装了杂乱的部分,并且不会将任何东西传递到安全继承链中。您也不需要为这种技术修改 Safety 类,使其更加模块化。这可能是许多较新的语言允许嵌套类但几乎没有其他任何东西都借用了朋友概念的原因,即使这只是添加了仅对单个类可用的功能(并且如果 Safety 标记为 final 或标记为重要则不起作用它的部分代码是私有的)。