C++ 是否可以在运行时选择可以访问类的私有成员的函数?
这个话题可能会让人困惑,但我相信我所追求的概念很容易理解 我有一个类,它有一些私有数据。我想提供一种方法,从类外部指定一个函数,该函数可以在运行时对这些数据进行操作。然而,我不想向公众公开这些数据 到目前为止,我有过这样的经历:C++ 是否可以在运行时选择可以访问类的私有成员的函数?,c++,c++11,C++,C++11,这个话题可能会让人困惑,但我相信我所追求的概念很容易理解 我有一个类,它有一些私有数据。我想提供一种方法,从类外部指定一个函数,该函数可以在运行时对这些数据进行操作。然而,我不想向公众公开这些数据 到目前为止,我有过这样的经历: #include <iostream> using namespace std; class Base{ double priv = 0; public: Base(double initial) : priv(initial) {};
#include <iostream>
using namespace std;
class Base{
double priv = 0;
public:
Base(double initial) : priv(initial) {};
double get_private(){ return priv; };
static void mix_privates(Base& b1, Base& b2);
};
void Base::mix_privates(Base& b1, Base& b2){
b1.priv = b2.priv = (b1.priv+b2.priv)/2;
}
//void Base::mix_privates(Base& b1, Base& b2){
// b1.priv = b2.priv = max(b1.priv, b2.priv);
//}
int main() {
Base test1(5), test2(10);
Base::mix_privates( test1, test2 );
cout << test1.get_private() << '\n';
cout << test2.get_private() << '\n';
return 0;
}
然后在main
中为某个通用名称指定一个具体实现,例如:
std::函数mix\u privates=mix\u privates\u avg
然后通过通用名称mix_privates(test1,test2)
使用mixer,直到程序的其余部分
如果mix_privates
只使用公共成员和属性,那么就没有问题了,我已经完成了。但我希望能够处理私人数据。除了这个功能之外,向公众公开它也没有任何意义,所以我想避免它
我曾考虑使用Friends,但它是不可继承的,这是一个缺点,并且不可转移,因此我认为我不能指定一个像代理一样的Friends函数
有没有办法在c++11中实现此功能或类似功能?您可以创建一个
Mixer
类,该类实现一个函数mix(Base&b1,Base&b2)
,并在Base
中声明它的一个实例。然后子类Mixer
来实现各种混合方式。将所需的Mixer
子类的实例分配给Base
中声明的实例,然后实现mix\u privates
来调用实例的mix
例如:
class Mixer;
class Base{
double priv = 0;
public:
...
static Mixer* mixer;
static void mix_privates(Base& b1, Base& b2) {
mixer->mix(b1, b2);
};
};
class Mixer {
public:
void mix(Base& b1, Base&b2) = 0;
};
class MixAverage : public Mixer {
public:
void mix(Base& b1, Base&b2) {
b1.priv = b2.priv = (b1.priv+b2.priv)/2;
};
}
main {
...
Base b1, b2;
Base::mixer = new MixAverage();
...
Base::mix_privates(b1, b2);
...
}
class Base{
double priv = 0;
public:
...
static Mixer* mixer;
static void mix_privates(Base& b1, Base& b2) {
mixer->mix(b1, b2);
};
friend class Mixer;
};
class Mixer {
public:
void mix(Base& b1, Base&b2) = 0;
int& priv(Base& b) {
return b.priv;
};
};
class MixAverage : public Mixer {
public:
void mix(Base& b1, Base&b2) {
priv(b1) = priv(b2) = (priv(b1)+priv(b2))/2;
};
}
这样做的问题是(正如所指出的,混音器
及其子类无法访问基
的私有成员。因此,您可以使Mixer
成为朋友,并实现子类可以使用的方法来访问base的私有成员。例如:
class Mixer;
class Base{
double priv = 0;
public:
...
static Mixer* mixer;
static void mix_privates(Base& b1, Base& b2) {
mixer->mix(b1, b2);
};
};
class Mixer {
public:
void mix(Base& b1, Base&b2) = 0;
};
class MixAverage : public Mixer {
public:
void mix(Base& b1, Base&b2) {
b1.priv = b2.priv = (b1.priv+b2.priv)/2;
};
}
main {
...
Base b1, b2;
Base::mixer = new MixAverage();
...
Base::mix_privates(b1, b2);
...
}
class Base{
double priv = 0;
public:
...
static Mixer* mixer;
static void mix_privates(Base& b1, Base& b2) {
mixer->mix(b1, b2);
};
friend class Mixer;
};
class Mixer {
public:
void mix(Base& b1, Base&b2) = 0;
int& priv(Base& b) {
return b.priv;
};
};
class MixAverage : public Mixer {
public:
void mix(Base& b1, Base&b2) {
priv(b1) = priv(b2) = (priv(b1)+priv(b2))/2;
};
}
您可以创建一个
Mixer
类来实现函数mix(Base&b1,Base&b2)
,并在Base
中声明它的一个实例。然后子类Mixer
来实现各种混合方式。将所需的Mixer
子类的实例分配给Base
中声明的实例,然后实现mix\u privates
来调用实例的mix
例如:
class Mixer;
class Base{
double priv = 0;
public:
...
static Mixer* mixer;
static void mix_privates(Base& b1, Base& b2) {
mixer->mix(b1, b2);
};
};
class Mixer {
public:
void mix(Base& b1, Base&b2) = 0;
};
class MixAverage : public Mixer {
public:
void mix(Base& b1, Base&b2) {
b1.priv = b2.priv = (b1.priv+b2.priv)/2;
};
}
main {
...
Base b1, b2;
Base::mixer = new MixAverage();
...
Base::mix_privates(b1, b2);
...
}
class Base{
double priv = 0;
public:
...
static Mixer* mixer;
static void mix_privates(Base& b1, Base& b2) {
mixer->mix(b1, b2);
};
friend class Mixer;
};
class Mixer {
public:
void mix(Base& b1, Base&b2) = 0;
int& priv(Base& b) {
return b.priv;
};
};
class MixAverage : public Mixer {
public:
void mix(Base& b1, Base&b2) {
priv(b1) = priv(b2) = (priv(b1)+priv(b2))/2;
};
}
这样做的问题是(正如所指出的,混音器
及其子类无法访问基
的私有成员。因此,您可以使Mixer
成为朋友,并实现子类可以使用的方法来访问base的私有成员。例如:
class Mixer;
class Base{
double priv = 0;
public:
...
static Mixer* mixer;
static void mix_privates(Base& b1, Base& b2) {
mixer->mix(b1, b2);
};
};
class Mixer {
public:
void mix(Base& b1, Base&b2) = 0;
};
class MixAverage : public Mixer {
public:
void mix(Base& b1, Base&b2) {
b1.priv = b2.priv = (b1.priv+b2.priv)/2;
};
}
main {
...
Base b1, b2;
Base::mixer = new MixAverage();
...
Base::mix_privates(b1, b2);
...
}
class Base{
double priv = 0;
public:
...
static Mixer* mixer;
static void mix_privates(Base& b1, Base& b2) {
mixer->mix(b1, b2);
};
friend class Mixer;
};
class Mixer {
public:
void mix(Base& b1, Base&b2) = 0;
int& priv(Base& b) {
return b.priv;
};
};
class MixAverage : public Mixer {
public:
void mix(Base& b1, Base&b2) {
priv(b1) = priv(b2) = (priv(b1)+priv(b2))/2;
};
}
提供一个定义受保护的getter/setter方法的friend类怎么样?这样,只有friend的派生类才能访问内部。例如:
class Base {
friend class Access;
...
private: double priv;
};
class Access {
protected:
double get_private(Base &b) { return b.priv; }
void set_private(Base &b, double priv) { b.priv = priv; }
public:
virtual void mix_privates(Base &b1, Base &b2) = 0;
};
class AccessMax : public Access {
void mix_privates(Base &b1, Base &b2) { set_private(b1, max(get_private(b1), get_private(b2)); }
};
提供一个定义受保护的getter/setter方法的friend类怎么样?这样,只有friend的派生类才能访问内部。例如:
class Base {
friend class Access;
...
private: double priv;
};
class Access {
protected:
double get_private(Base &b) { return b.priv; }
void set_private(Base &b, double priv) { b.priv = priv; }
public:
virtual void mix_privates(Base &b1, Base &b2) = 0;
};
class AccessMax : public Access {
void mix_privates(Base &b1, Base &b2) { set_private(b1, max(get_private(b1), get_private(b2)); }
};
<> P>与其他建议相反,我会考虑制作<代码> MixuSubase[/COD> >一个模板,该模板具有一个实际混合的函数:
template <typename Functor>
void Base::mix_privates(Base& b1, Base& b2, Functor f) {
b1.priv = b2.priv = f(b1,b2);
}
模板
void Base::mix\u privates(基本&b1、Base&b2、Functor f){
b1.priv=b2.priv=f(b1,b2);
}
然后您可以使用它:
Base b1(..), b2(..);
Base::mix_privates(b1,b2,
[](double x, double y) { return (x+y)/2; }); // average
Base::mix_privates(b1,b2,
&std::max<double>); // max
基准b1(..)、b2(..);
基层:混合料(b1、b2、,
[](双x,双y){返回(x+y)/2;});//平均的
基层:混合料(b1、b2、,
&标准:最大值);//最大值
与其他建议相反,我会考虑制作<代码> MixyPuulase<代码>,该模板采用了一个实际混合的函数:
template <typename Functor>
void Base::mix_privates(Base& b1, Base& b2, Functor f) {
b1.priv = b2.priv = f(b1,b2);
}
模板
void Base::mix_privates(Base&b1,Base&b2,函子f){
b1.priv=b2.priv=f(b1,b2);
}
然后您可以使用它:
Base b1(..), b2(..);
Base::mix_privates(b1,b2,
[](double x, double y) { return (x+y)/2; }); // average
Base::mix_privates(b1,b2,
&std::max<double>); // max
基准b1(..)、b2(..);
基层:混合料(b1、b2、,
[](双x,双y){返回(x+y)/2;});//平均的
基层:混合料(b1、b2、,
&标准:最大值);//最大值
是否有任何东西可以排除二传手?类似的东西void Base::set(double a){priv=a;}
。这对您来说太多了吗?封装是一种编译时特性。在运行时没有公共/私有/受保护的概念。为什么不能使用get_private()
和set_private()
来访问数据?因此,您不想让更改私有数据变得容易,但希望能够编写任意数量的可以更改私有数据的无关函数?真正的数据更像二进制数据。我不想让它暴露在全世界。我只是遇到了一种情况,我可以概括和重构操作私有数据的函数。我认为这样做是个好主意,但我不认为这是污染公共空气污染指数的理由。我希望有一类函数能够访问私有数据。例如,从某个BaseMixer
派生的函子将是友元。或者类似的事情。有什么东西可以排除二传手吗?类似的东西void Base::set(double a){priv=a;}
。这对您来说太多了吗?封装是一种编译时特性。在运行时没有公共/私有/受保护的概念。为什么不能使用get_private()
和set_private()
来访问数据?因此,您不想让更改私有数据变得容易,但希望能够编写任意数量的可以更改私有数据的无关函数?真正的数据更像二进制数据。我不想让它暴露在全世界。我只是遇到了一种情况,我可以概括和重构操作私有数据的函数。我认为这样做是个好主意,但我不认为这是合理的