Hi, I hope this helps in some way. Note: I have no clue what your

problem domain is but I have some indication that the following

sample code will help you in some way. BTW, I did NOT try to compile

the code. I merely wrote it to give you some idea.

Good Luck!

PS. I like to use boost. If you don't, RcPtr can be replaced with

a raw pointer. (

www.boost.org)

-------------------------------------------------------------------

#include <boost/shared_ptr.hpp>

class IntegratorImpl

{

public:

typedef boost::shared_ptr<IntegratorImplRcPtr;

public:

IntegratorImpl( double a ) : m_a( a ) {}

virtual bool integrate() = 0;

protected:

// I think that a should be here not in Body

// but I don't know what a is.

double m_a;

};

class EulerIntegrator : public IntegratorImpl

{

public:

EulerIntergrator( double a ) : IntegratorImpl( a ) {}

virtual bool integrate()

{

// do Euler integration

}

private:

// put Euler integration specific stuff here

};

// add Vertlet and LeapFrog integrators as separate classes like

// EulerIntegrator

class Integrator

{

public:

enum IntegrateType

{

kNone, kEuler, kVertlet, kLeapFrog

};

public:

Integrator();

~Integrator();

void selectIntegrator( Integrator type, double a )

{

switch( type )

{

case kEuler:

m_impl.reset( new EulerIntegrator( a ));

break;

case kVertlet:

m_impl.reset( new VertletIntegrator( a ));

// you get the idea

default:

// throw? your choice

}

}

bool integrate()

{

if( m_impl )

{

return false;

}

else

{

return m_impl->integrate();

}

}

private:

// just a raw pointer if you do not like boost

IntegratorImpl::RcPtr m_impl;

};

class Body

{

public:

Body();

bool integrate() { return m_integrator.integrate(); }

virtual void selectIntegrator( Integrator::IntegratorType type )

{

// assuming 0 is a good default for a here

m_integrator.selectIntegrator( type, 0 );

}

private:

Integrator m_integrator;

// rest of your data members here

};

class Planet : public Body

{

public:

Planet( const Body &body ) : m_body( body ) {}

double calcForce()

{

// use m_body to calculate a here

double a = 1.0;

return a;

}

virtual void selectIntegrator( Integrator::IntegratorType type )

{

m_integrator.selectIntegrator( type, calcForce() );

}

private:

const Body &m_body;

};

// something similar for SimpleHarmonic

int

main(void)

{

Planet p;

Planet p2;

SimpleHarmonic s;

p.selectIntegrator( Integrator::kLeapFrog );

p2.selectIntegrator( Integrator::kVertlet );

s.selectIntegrator( Integrator::kVertlet );

cout << "planet,leapfrog: ";

p.integrate();

cout << "planet,verlet: ";

p2.integrate();

cout << "simpleharmonic,verlet: ";

s.integrate();

return 0;

}

nw wrote:

Hi,

I was wondering if someone would be able to give me some comments on

the following class structure, it feels to me as if there must be a

better way, but I'm unsure what it is, perhaps I should be using

multiple inheritance?

Basically I have a pure virtual class called Body, this contains a

number of integration algorithms which are applied to the Body.

Generally only one integration algorithm will be used with a

particular Body. The integration algorithm is called by the

integrate() method, which selects the integration algorithm depending

on how you have set the variable integration_type.

I'm not sure if it's relevant to this discussion but Body is the base

class from which two others are derived, these implement the

calculate_force() method, this method updates a variable used by the

integrate() method.

Compilable example code implementing this design follows. Apologies if

I've been overly verbose.

Any help greatly appreciated!

#include <iostream>

using namespace std;

class Body {

public:

double x, y, z;

double a;

static const int BODY_INTEGRATE_EULER=1;

static const int BODY_INTEGRATE_VERLET=2;

static const int BODY_INTEGRATE_LEAPFROG=3;

int integration_type;

virtual bool calculate_force(Body &b) = 0;

Body() {

integration_type=BODY_INTEGRATE_EULER;

}

bool integrate() {

if(integration_type == BODY_INTEGRATE_EULER) {

// .. do euler

cout << "Euler integration" << endl;

return true;

} else

if(integration_type == BODY_INTEGRATE_VERLET) {

// .. do verlet

cout << "Verlet integration" << endl;

return true;

} else

if(integration_type == BODY_INTEGRATE_LEAPFROG) {

// .. do leapfrog

cout << "Leapfrog integration" << endl;

return true;

}

}

};

class Planet : public Body {

virtual bool calculate_force(Body &b) {

// do force calculation for planet... updates a

}

};

class SimpleHarmonic : public Body {

virtual bool calculate_force(Body &b) {

// do force calculation for simple harmonic motion... updates a

}

};

int main(void) {

Planet p;

Planet p2;

SimpleHarmonic s;

p.integration_type = Body::BODY_INTEGRATE_LEAPFROG;

p2.integration_type = Body::BODY_INTEGRATE_VERLET;

s.integration_type = Body::BODY_INTEGRATE_VERLET;

cout << "planet,leapfrog: ";

p.integrate();

cout << "planet,verlet: ";

p2.integrate();

cout << "simpleharmonic,verlet: ";

s.integrate();

return 0;

}