Re: Static member function in abstract base class

From: Robert C. Martin (unclebob_at_objectmentor.com)
Date: 02/12/04


Date: Thu, 12 Feb 2004 09:46:28 -0600

On 12 Feb 2004 01:31:49 -0800, a_calafato@virgilio.it (yan) wrote:

>Hello! I have a problem of design of a class.
>have an Abstract Base Class used as base class for differentes
>Derived classes. The derived classes must able to set the behavior
>of a function f() at run-time. I want use the same function behavior
>also in Another Class, but without using inheritance because
>Another Class not extend Base Class.
>
>I have used a function pointer and static members function declared
>in Base Class for differentes implementation of the function f().
>
>Is correct? or is convenient to define a new class to share common
>functionalities between Derived and Another class? The code work
>perfectly. My doubt is: is correct to define static member function
>in an Abstract Base class? Is logically wrong?
>
>Here is the example code.
>
>code:
>class AbstractBaseClass {
>public:
> virtual int f(int a, int b) = 0;
> virtual void setImplementation(int implType) = 0;
> static int fImplementationOne(int a, int b) {
> return a+b;
> }
> static int fImplementationTwo(int a, int b) {
> return a-b;
> }
>};
>
>class DerivedClass : public AbstractBaseClass {
>public:
> DerivedClass(int implType) {
> setImplementation(implType);
> }
> void setImplementation(int implType) {
> if (implType == 0)
> _f = &AbstractBaseClass::fImplementationOne;
> else
> _f = &AbstractBaseClass::fImplementationTwo;
> }
> int f(int a, int b) {
> return _f(a, b);
> }
>private:
> int (*_f)(int a, int b);
>};
>
>class AnotherClass {
>public:
> AnotherClass() {
> _f = &AbstractBaseClass::fImplementationOne;
> }
>private:
> int (*_f)(int a, int b);
>};
>
>int main()
>{
> AnotherClass a;
> AbstractBaseClass *c = new DerivedClass(0);
> cout << c->f(10,3) << '\n';
> c->setImplementation(1);
> cout << c->f(10,3) << '\n';
>}

This works, but I don't like using pointers to functions. I suggest
you use the command pattern instead.

class BinaryOperator
{
  virtual int f(int a, int b) = 0;
};

class Difference : public BinaryOperator
{
  virtual int f(int a, int b) {return a-b;}
};

class Sum : public Binary Operator
{
  virtual int f(int a, int b) {return a+b;}
};

class AbstractBaseClass {
public:
        virtual int f(int a, int b) = 0;
        virtual void setImplementation(int implType) = 0;

  static Sum _sum;
  static Difference _difference
};

class DerivedClass : public AbstractBaseClass {
public:
        DerivedClass(int implType) {
                setImplementation(implType);
        }
        void setImplementation(int implType) {
                if (implType == 0)
                        operator = &_sum;
                else
                        operator = &_difference;
        }
        int f(int a, int b) {
                return operator->f(a, b);
        }

private:
        BinaryOperator* operator;
};

class AnotherClass {
public:
        AnotherClass() {
                operator = AbstractClass::sum;
        }

  int f(a,b) {return operator->f(a,b);}
private:

        BinaryOperator* operator;
};

int main()
{
        AnotherClass a;
        AbstractBaseClass *c = new DerivedClass(0);
        cout << c->f(10,3) << '\n';
        c->setImplementation(1);
        cout << c->f(10,3) << '\n';
}

---------------------------------------------------
Of course this means that you could really do this:
---------------------------------------------------

class BinaryOperator
{
  virtual int f(int a, int b) = 0;
};

class Difference : public BinaryOperator
{
  virtual int f(int a, int b) {return a-b;}
};

class Sum : public Binary Operator
{
  virtual int f(int a, int b) {return a+b;}
};

class AbstractBaseClass {
public:
        virtual int f(int a, int b) = 0;
        virtual void setImplementation(BinaryOperator*) = 0;
};

class DerivedClass : public AbstractBaseClass {
public:
        DerivedClass(BinaryOperator* op) {
                setImplementation(op);
        }
        void setImplementation(BinaryOperator* op) {
                operator = op;
        }

        int f(int a, int b) {
                return operator->f(a, b);
        }

private:
        BinaryOperator* operator;
};

class AnotherClass {
public:
        AnotherClass() {
                operator = sum;
        }

  int f(a,b) {return operator->f(a,b);}
private:
  static Sum sum;
        BinaryOperator* operator;
};

int main()
{
  Sum sum;
  Difference difference;

        AnotherClass a;
        AbstractBaseClass *c = new DerivedClass(&sum);
        cout << c->f(10,3) << '\n';
        c->setImplementation(&difference);
        cout << c->f(10,3) << '\n';
}



Relevant Pages

  • Re: How Do I Prevent Copying From Base Class?
    ... Why do I need "int getID() {return ... Class A, Class B, and Class C are derived from Color Class that they can ... It allows three derived classes to "point indirectly" ... which copy of the base class members you want whenever you access them. ...
    (comp.lang.cpp)
  • Re: Virtual base class constructor
    ... overrides a virtual function that it inherits from a virtual base class, ... virtual void foo() ...
    (microsoft.public.vc.language)
  • Re: Game object class design problem
    ... I have a class design which has a base class and then derived ... int getFeatureIntParam; ... void setFeatureIntParam(FeatureId id, int paramNum, int value); ... ObjectClass *npcs =new ObjectClass; ...
    (rec.games.roguelike.development)
  • Re: Inhertance Question
    ... which is the base class for all forms. ... > public class DerivedTypeA: BaseType { ... > public int Length { ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: need interface methods to be virtual-able
    ... public override int CompareTo(object obj) { ... What I see is that the "CompareTo" coming from IComparable should be ... DerivedClass d1 = new DerivedClass; ...
    (microsoft.public.dotnet.general)