我正在使用一些代码,我有以下设置。
struct data
{
void change_safe_member(){}
void read_data(){}
void change_unsafe_member(){}
};
struct data_processor
{
std::shared_ptr<data> get_data(){}
void return_data(std::shared_ptr<data> my_data)
{
my_data->change_unsafe_member(); // ONLY data_processor should call this function.
}
};
struct client
{
void foo(std::shared_ptr<data_processor>& my_processor)
{
auto my_data = my_processor->get_data();
my_data->change_safe_member();
//my_data->change_unsafe_member(); SHOULD NOT BE POSSIBLE TO CALL
my_processor->return_data(my_data);
}
};
change_unsafe_member应该只在处理器内部使用,所以我想隐藏它或为客户端禁用它。但是我不知道有什么好办法可以做到这一点而不诉诸丑陋的演员......
struct internal_data
{
void change_unsafe_member(){}
};
struct data : public internal_data
{
void change_safe_member(){}
void read_data(){}
};
struct data_processor
{
std::shared_ptr<data> get_data(){}
void return_data(std::shared_ptr<data> my_data)
{
auto internal_data = std::static_pointer_cast<internal_data>(my_data);
internal_data->change_unsafe_member();
}
};
任何人都知道在这种情况下使用的好模式?也许访客模式或类似的东西?
编辑:
正如评论中所指出的那样,可以申报朋友类,但是有一个问题......以下内容不起作用。
struct data
{
void change_safe_member(){}
void read_data(){}
private:
friend class data_processor;
virtual void change_unsafe_member(){}
};
struct data_decorator : public data
{
data_decorator(const std::shared_ptr<data>& decoratee) : decoratee_(decoratee){}
void change_safe_member(){decoratee_->change_safe_member();}
void read_data(){decoratee_->read_data();}
private:
virtual void change_unsafe_member()
{
std::cout << "Hello!"; // Add functionality
decoratee_->change_unsafe_member(); // Won't work... compiler error
}
std::shared_ptr<data> decoratee_;
};
// Another example
struct data_group_decorator : public data
{
data_group_decorator (const std::vector<std::shared_ptr<data>>& decoratees) : decoratees_(decoratees){}
void change_safe_member(){decoratee_->change_safe_member();}
void read_data(){decoratee_->read_data();}
private:
virtual void change_unsafe_member()
{
for(size_t n = 0; n < decoratees_.size(); ++n)
decoratees_[n]->change_unsafe_member(); // Won't work... compiler error
}
std::vector<std::shared_ptr<data>> decoratees_;;
};
答案 0 :(得分:1)
你的最后一个例子看起来像你真正要求的是继承的友谊;即,您希望拥有decorator
层次结构 - 派生类,这些类都可以在private
中调用data
成员函数。在其他地方得到了回答(通常没有“):
Why does C++ not allow inherited friendship?
多态性可能会在您的特定场景中提供一些缓解,使class data_decorator
成为“几乎纯粹的”虚拟基类,唯一的非虚拟成员为protected change_unsafe_member()
,并将其作为{{1} } friend
。所有装饰器都将从class data
继承,并调用其受保护的非虚拟成员。
答案 1 :(得分:1)
你可以通过继承实现这一点。
struct Y;
struct X {
friend struct Y;
private:
change_unsafe_member() {}
};
struct Y {
protected:
change_unsafe_member(X& x) { x.change_unsafe_member(); }
};
struct some_other : Y {
X x;
change_safe_member() { change_unsafe_member(x); }
};
任何从Y继承的类都可以为Y定义为X的任何函数获得X的友谊。