Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否可以在运行时选择可以访问类的私有成员的函数?_C++_C++11 - Fatal编程技术网

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()
来访问数据?因此,您不想让更改私有数据变得容易,但希望能够编写任意数量的可以更改私有数据的无关函数?真正的数据更像二进制数据。我不想让它暴露在全世界。我只是遇到了一种情况,我可以概括和重构操作私有数据的函数。我认为这样做是个好主意,但我不认为这是合理的