1

I would like to know what the following paragraph means and how do I implement it. I asked a question yesterday related to the same issue here. In yesterday's question, I was told this is not possible but I think the following paragraph indicates it is?

Your methods use specific exponentiation methods. However, the exponentiation classes are subclasses of a general abstract exponentiation class. You could implement these to use this abstract class, and just instantiate that with one of the concrete classes. This would give you the flexibility to experiment with and/or change exactly what exponentiation algorithms are used, for example, if someone identifies something better in the future....

Essentially, I have a bunch of exponentiation techniques organized in the following manner-

template <class T>
class Exponentiation
{
    public:
    Exponentiation() {};
    virtual ~Exponentiation() {};

    // computes C = A^n
    virtual void power(T& C, const T& A, const int n) = 0;
}

template <class T>
class ExpA : public Exponentiation<T>
{
    public:
    ExpA() {};
    ~ExpA() {};

    void power (T& C, const T& A, const int n);
}

template <class T>
class ExpB : public Exponentiation<T>
{
    protected:
    var1;
    var2;

    public:
    ExpB() {};
    ~ExpB() {};

    func1();
    func2();
    void power (T& C, const T& A, const int n);
}

Now, initially I had a performExp() that was calling specific exponentiation methods like -

performExp()
{
    ExpA<long> objA;
    objA.power();

    // or

    ExpB<long> objB;
    objB.func1();
    objB.func2();
    obj.power ()
}

but from what I have been told, a better option is to use the base class in performExp() and then instantiate the base class in main() with one of the concrete classes ExpA or ExpB.

How does one go about doing this? One thought I have after reading yesterday's answers is to use some sort of wrapper but I am having a hard time to visualize it.

Papa Delta
  • 267
  • 3
  • 12
  • 1
    You just pass a pointer or reference (depends on situation) to the base class to your function. – Slava Aug 20 '18 at 15:16
  • 1
    Look up "polymorphism". – Peter Aug 20 '18 at 15:17
  • The paragraph you quoted is a bit vague but I think use of the [Dependency Injection Pattern](https://en.wikipedia.org/wiki/Dependency_injection) might address your needs. – R Sahu Aug 20 '18 at 16:07
  • @Slava I tried your suggestion but it doesn't let me call `func1` or `func2` . The error I receive is `no member named 'func1' in Exponentiation` – Papa Delta Aug 20 '18 at 16:54
  • @Mojo-Jojo all methods you would call must be defined in base class, probably as virtual and maybe pure virtual. Alternative is using `dynamic_cast<>` but that is usually a sign of bad design. – Slava Aug 20 '18 at 22:04

1 Answers1

1

I don't see exactly what you are trying to achieve. But the first question is whether you need to have a run-time or a compile-time polymorphism. Looking at your code, I guess it's the latter.

So I'll assume for this answer that you have your templated exponentiation classes and that you write in the end compelx calculation programms that will know exactly if they work on an ExpA or an ExpB.

I'd then suggest to implement performExp() as a template function to indicate in a generic way how to perform the operation:

template <class T, template <class U> class Exp>
void performExp(Exp<T>& obj)
{
     obj.power();
}

It is then possible to provide specialisations or partial specialisations for this template:

template <class T>
void performExp(ExpB<T>& obj)
{
     obj.func1();
     obj.func2(); 
     obj.power();
}

When you then use these templates in your code, the compiler will deduce the parameters and use any specialization that may exist:

int main() {
    ExpA<long> a;
    performExp(a);

    ExpB<long> b; 
    performExp(b);       //specialized form will be used
}

You can test the result in this online demo

Christophe
  • 68,716
  • 7
  • 72
  • 138