C++定义虚基类重载运算符

标签 c++ operator-overloading functor

我正在尝试编写一组通用数学实用程序类(根查找器、积分器等),这些类在构造时接受一个指向基类的指针,该基类定义了我希望特定算法运行的函数。基类应该只定义一个公共(public)虚拟接口(interface)(抽象的或具有默认的琐碎功能)type operator()(type inputArg),用户可以根据需要实现。这将允许用户只实现所需的仿函数并执行所需的计算。我的 mwe 在下面:

第一个头文件定义了抽象接口(interface)类

// BaseFunctor.h

#ifndef _BASE_FUNCTOR_H_
#define _BASE_FUNCTOR_H_

class BaseFunctor
{
public:
   virtual double operator() (double x) = 0;
};
#endif

这是求解器方法之一的类

// NewtonsMethod.h

#ifndef _NEWTONS_METHOD_H_
#define _NEWTONS_METHOD_H_

class BaseFunctor;

class NewtonsMethod
{
public: 

   NewtonsMethod(BaseFunctor *rhsIn,
                 BaseFunctor *rhsPrimeIn,
                 double       x0In);

   ~NewtonsMethod();

   bool DetermineRoot(double &root);

 private:

   double       x0;
   BaseFunctor *rhs;
   BaseFunctor *rhsPrime;

   static const double       EPSILON;
   static const unsigned int MAX_ITER;

};
#endif

这是求解器的实现: //牛顿方法.cpp

#include "NewtonsMethod.h"
#include "BaseFunctor.h"
#include <cmath>

const double       NewtonsMethod::EPSILON  = 1e-9;
const unsigned int NewtonsMethod::MAX_ITER = 30;

NewtonsMethod::NewtonsMethod(BaseFunctor *rhsIn,
                             BaseFunctor *rhsPrimeIn,
                             double       x0In) :
   rhs     (rhsIn),
   rhsPrime(rhsPrimeIn),
   x0      (x0In)
{ }

NewtonsMethod::~NewtonsMethod() { }

bool NewtonsMethod::DetermineRoot(double &root)
{
   // This is obviously not implemented
   root = rhs(1.0) / rhsPrime(2.0);
   return false;
}

以及我创建派生类实现的主要函数: // main.cpp

#include "BaseFunctor.h"
#include "NewtonsMethod.h"
#include <iostream>
#include <iomanip>

class fOfX : public BaseFunctor
{
   double operator() (double x)
   {
      return x * x - 2.0;
   }
};

class fPrimeOfX : public BaseFunctor
{
   double operator() (double x)
   {
      return 2.0 * x;
   }
};


int main()
{
   double x0 = 2.0;

   BaseFunctor *f      = new fOfX();
   BaseFunctor *fPrime = new fPrimeOfX(); 

   NewtonsMethod newton(f, fPrime, x0);

   double root      = 0.0;
   bool   converged = newton.DetermineRoot(root);

   if (converged)
   {
      std::cout << "SUCCESS: root == " << std::setprecision(16) << root << std::endl;
   }
   else
   {
      std::cout << "FAILED: root == " << std::setprecision(16) << root << std::endl;
   }
   delete f;
   delete fPrime;
}

我尽量简短,如果太长,请见谅。基本上我得到错误:

g++ Main.cpp NewtonsMethod.cpp -o main
NewtonsMethod.cpp: In member function ‘bool NewtonsMethod::DetermineRoot(double&)’: 
NewtonsMethod.cpp:29: error: ‘((NewtonsMethod*)this)->NewtonsMethod::rhs’ cannot be used    as a function
NewtonsMethod.cpp:29: error: ‘((NewtonsMethod*)this)->NewtonsMethod::rhsPrime’ cannot be   used as a function

我怎样才能解决这个问题,保持所需的功能或为各种需要的功能派生一个类?

谢谢

最佳答案

rhsrhsPrime 是指针。您需要引用它们才能调用函数调用运算符。

(*rhs)(1.0) / (*rhsPrime)(2.0)

如果 rhsrhsPrime 是必需的(即不能为 NULL)并且在 NewtonsMethod 对象具有构造函数后不能更改,您应该声明它们作为引用而不是指针。这也消除了取消引用它们以调用函数调用运算符的需要。

下面的例子展示了如何使用引用来引用仿函数。

class NewtonsMethod
{
public: 
   NewtonsMethod(BaseFunctor& rhsIn,
                 BaseFunctor& rhsPrimeIn,
                 double       x0In);

   ~NewtonsMethod();

   bool DetermineRoot(double &root);

 private:

   double       x0;
   BaseFunctor& rhs;
   BaseFunctor& rhsPrime;

   static const double       EPSILON;
   static const unsigned int MAX_ITER;
};

int main()
{
   double x0 = 2.0;

   fOfX       f;
   fPrimeOfX  fPrime;

   NewtonsMethod newton(f, fPrime, x0);
}

……或者……

int main()
{
   double x0 = 2.0;

   BaseFunctor *f      = new fOfX();
   BaseFunctor *fPrime = new fPrimeOfX(); 

   NewtonsMethod newton(*f, *fPrime, x0);

   // ... other code including delete for the functors
}

关于C++定义虚基类重载运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17460480/

相关文章:

c++ - 将可调用的 std::function() 重定向到 C++11 之前的自定义处理程序?

c++ - sqlite3程序收到信号SIGSEGV,sqlite3_get_table()中出现段错误

c++ - Boost Beast 异步服务器因断言失败而失败:(id_!= T::id) 在多个 aync 调用中

c++ - 为什么我的 vector 不能识别我的派生类?

c++ - 重载 += 或 -= 运算符的好处

c++ - 基于非静态数据成员自动生成构造函数?

c++ - 如何从 std::ofstream 获取文件 ID

c++ - 当我使用非 cst 内存模型时,为什么我的自旋锁实现性能最差?

c++ - 用继承和多态重载 '<<'?

c++ - 使用非常量表达式作为模板参数