根据C 中的变量值创建成员函数

Create member function according to variable value in C++

本文关键字:创建 成员 函数 变量值 根据      更新时间:2023-10-16

原始代码太复杂了,所以我抽象出以下问题:

class A {
  public:
    A (int p): _p{p} {}
    float computeA (float a) {
      if (_p == 0)
        return 0.1f + expf(a);
      else if (_p == 1)
        return 0.2f + sqrtf(a);
      else if (_p == 2)
        return 0.3f + sinf(a);
      return 0.4f +cosf(a);
    }
    float accumulate() {
      ...
      for(...) {
        int temp = computeA();
        // other calculations...
      }
      ...
    }
    ...
  private:
    const int _p;
};

_p a 中的常数成员,只能是0、1、2或3。strong>取决于 _p 的值。由于在创建 a 时已经知道 _P ,因此我想知道是否有适当的方法可以避免代码中的" IF"条件。

仅更改每个子类的一行代码( a ),多态性不实用(或它是?)strong>有所作为)。另一个问题可能是性能,因为简单的 computea()经常以重 comgumulate()的大回路调用。多态函数调用的开销会变得不可接受吗?

谢谢,

您可以使用简单的功能指针:

float compute0(float a) { return 0.1f + expf(a); }
float compute1(float a) { return 0.2f + sqrtf(a); }
float compute2(float a) { return 0.3f + sinf(a); }
float compute3(float a) { return 0.4f + cosf(a); }
class A {
  public:
    typedef float (*functype)(float);
    A (int p) {
      switch (p) {
        case 0:  _func = &compute0; break;
        case 1:  _func = &compute1; break;
        case 2:  _func = &compute2; break;
        default: _func = &compute3; break;
    }
    float computeA (float a) {
      return _func(a);
    }
    ...
  private:
    functype _func;
};

或,如果您想喜欢它,则可以使用lambdas:

class A {
  public:
    A (int p) {
      switch (p) {
        case 0:  _func = [](float a) { return 0.1f + std::exp(a); }; break;
        case 1:  _func = [](float a) { return 0.2f + std::sqrt(a); }; break;
        case 2:  _func = [](float a) { return 0.3f + std::sin(a); }; break;
        default: _func = [](float a) { return 0.4f + std::cos(a); }; break;
    }
    float computeA (float a) {
      return _func(a);
    }
    ...
  private:
    std::function<float(float)> _func;
};

另外,让创建A对象的代码决定要计算的值和功能:

class A {
  public:
    typedef float (*functype)(float);
    A (float value, functype func) :
      _value(value), _func(func)
    }
    float computeA (float a) {
      return _value + _func(a);
    }
    ...
  private:
    const float _value;
    const functype _func;
};

A a1(0.1f, &expf);
A a2(0.2f, &sqrtf);
A a3(0.3f, &sinf);
A a4(0.4f, &cosf);

或:

class A {
  public:
    using functype = std::function<float(float)>;
    A (float value, functype func) :
      _value(value), _func(func)
    }
    float computeA (float a) {
      return _value + _func(a);
    }
    ...
  private:
    const float _value;
    const functype _func;
};

A a1(0.1f, std::exp);
A a2(0.2f, std::sqrt);
A a3(0.3f, std::sin);
A a4(0.4f, std::cos);

或使用多态性,让呼叫者决定要使用哪个子类(甚至创建自己的子类以进行自定义计算):

class A {
  public:
    A () {}
    virtual float computeA (float a) = 0;
    ...
};
class A_exp : public A {
  public:
    float computeA (float a) override { return 0.1f + std::exp(a); }
};
class A_sqrt : public A {
  public:
    float computeA (float a) override { return 0.2f + std::sqrt(a); }
};
class A_sin : public A {
  public:
    float computeA (float a) override { return 0.3f + std::sin(a); }
};
class A_cos : public A {
  public:
    float computeA (float a) override { return 0.4f + std::cos(a); }
};

A_exp a1;
A_sqrt a2;
A_sin a3;
A_cos a4;

多态性不实用(或它是?),仅更改每个子类的一行代码...

确定是。基本类型具有所有相同的代码,除了computeA(),它变为纯虚拟的:

float computeA(float) = 0;

然后,每个基础仅覆盖该方法。

请注意,如果间接函数调用开销是可以接受的(请参见以下部分),那么您可以让构造函数取一个std::function<float(float)>,然后让呼叫者通过expfsqrtf等通过,等等。这样,您就不需要子课,并且类消费者不仅限于四个功能 - 它们也不仅限于仅限功能(函数变得可行)。

多态函数调用的开销会变得不可接受吗?

这是一个很好的问题,您应该通过对两个选项进行基准测试。


如果您坚持有条件的方法,请提出一些建议:

  • _p应该更恰当地是class enum类型,以使您没有魔术数字在代码中流动。
  • 考虑使用switch代替if。由于通常以计算机为goto实现,因此它具有更快的速度。(但是,智能编译器可能会将您的多条条件优化为单个计算机。)