2013-07-04 3 views
1

Я пытаюсь написать набор общих классов математической утилиты (корневых искателей, интеграторов и т. Д.), Которые принимают при построении указатель на базовый класс, который определяет функцию, которую я хочу специфический алгоритм для работы. Базовый класс должен определять только виртуальный виртуальный интерфейс (абстрактное или стандартная тривиальная функциональность) type operator()(type inputArg), который может быть реализован пользователем по мере необходимости. Это позволит пользователю просто реализовать нужные функторы и выполнить необходимые вычисления. Мой м.в.э. ниже:C++ Определение перегруженного оператора виртуального базового класса

Это первый заголовок определяет абстрактный класс интерфейса

// 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 

Это реализация решателя: // NewtonsMethod.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 

Как я могу получить это разрешить сохранение требуемой функциональности или получения класса для различных нужных функций?

Благодаря

ответ

1

rhs и rhsPrime являются указателями. Вы должны ссылаться на них, чтобы вызвать вызов оператора функции.

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

rhs Если и rhsPrime требуется (т.е. не может быть 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 
} 
+0

Спасибо! Развертывание их работы, хотя и является уродливым решением. Как взять их в качестве ссылок, поскольку я имею в виду их как объект BaseClass? Я не могу статически выделять их в основном, правильно? – JohnML

+0

Я обновил свой ответ, чтобы включить пример использования ссылок. Конечно, вам все равно нужно убедиться, что объекты-функторы имеют время жизни, равное или большее, чем объект «NewtonsMethod». –

+0

Большое спасибо за разъяснение. У меня никогда не было привязки класса к статически созданным объектам в качестве переменных-членов (только указатели (или значения ...)). Это работает по своему желанию и является более чистым, чем разыменование, а также новое/удаление. – JohnML