0

For a university project we have to create several classes, all depending on the abstract class function.

But while trying to define the class Compose, which has to combine two different functions passed as constructor arguments, I get several problems as shown below.

How exactly can I use my abstract class as a data type without problems in this case?

Abstract Class Function:

class Function{
protected:
    double _a, _b, _c, _m;
public:
    Function(double a, double b, double c, double m): _a(a), _b(b), _c(c), _m(m){}
    virtual double evaluate(double x) =0;
    void print(){ for(double i=0.0; i==1.0; i+=0.1) cout << "Wert: " << i << ", Ergebnis: " << evaluate(i) << endl;}
};

Class Compose:

class Compose:public Function{
private:
    Function *_f1, *_f2;
public:
    Compose(Function & f1, Function & f2):Function(0,0,0,0), _f1(f1), _f2(f2){}
    double evaluate(double x){}
};

Error Messages:

21:54:02 **** Incremental Build of configuration Debug for project Aufgabe_10_1 ****
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -std=c++11 -o "src\\Aufgabe_10_1.o" "..\\src\\Aufgabe_10_1.cpp" 
..\src\Aufgabe_10_1.cpp: In constructor 'Compose::Compose(Function&, Function&)':
..\src\Aufgabe_10_1.cpp:37:7: error: cannot convert 'Function' to 'Function*' in assignment
   _f1 = f1;
       ^
..\src\Aufgabe_10_1.cpp:38:7: error: cannot convert 'Function' to 'Function*' in assignment
   _f2 = f2;
       ^
..\src\Aufgabe_10_1.cpp: In member function 'virtual double Compose::evaluate(double)':
..\src\Aufgabe_10_1.cpp:40:28: warning: no return statement in function returning non-void [-Wreturn-type]
  double evaluate(double x){}
                            ^

21:54:03 Build Finished (took 423ms)
Steve Vinoski
  • 19,847
  • 3
  • 31
  • 46
  • 2
    You seem to be unsure of whether `Compose` manages pointers to `Function` or references to `Function`. They are not the same. Which did you want? – Drew Dormann Jan 10 '15 at 20:39
  • I think you must mean `Compose(Function * f1, Function * f2):_f1(f1), _f2(f2){}` – TonyK Jan 10 '15 at 20:43
  • it has to manage with references, cause the function types shall be references. I only used Pointers in Compose, cause the compiler didn't let me use any other, because i can't create any objects of functon itself due to the fact that it's an abstract class – TheStriker0815 Jan 10 '15 at 20:44

2 Answers2

0

First problem:

Half of your errors can be reduced to something like this:

Function &a = ...;
Function *b = a;

With what you've shown above, that just doesn't make any sense.

Second problem:

Function doesn't have a constructor that takes zero parameters. So you need to explicitly call a constructor of it in the constructor of Compose. Perhaps something like:

class Compose:public Function{
    private:
        Function *_f1, *_f2;
    public:
        Compose(Function *f1, Function *f2): Function(0,1,2,3), _f1(f1), _f2(f2) {}
        double evaluate(double x) {}
};
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • this won't work, because no objects can be created of Function, because it's abstract :/ EDIT: ah okay, i'll try out I completely forgot that all variables of function have to be initialised wether i use them or not – TheStriker0815 Jan 10 '15 at 20:46
  • @TheStriker0815: Not exactly. It's not that they need to be initialized. It's that your parent class `Function` needs to have a constructor called on it. You've provided one, and it takes four arguments. You could also provide one that requires no arguments. What that means is up to the logic of your full program. – Bill Lynch Jan 10 '15 at 20:51
  • Okay that worked out well, thanks ! now the only Problem is that one with the reference to pointer convertion thing – TheStriker0815 Jan 10 '15 at 20:52
0

Pointers and references can refer to abstract types. Inside your Compose class, you've declared the pointer members _f1 and _f2 which is fine. However, you cannot assign a reference to a pointer so you should change Compose's constructor to also take pointers as arguments.

class Compose : public Function
{

private:

  Function *_f1, *_f2;  // these are pointers

public:

  Compose(Function & f1, Function & f2) : _f1(f1), _f2(f2)
  {    //  ^^^  references here  ^^^      ^^^ problem there ^^^
  }

  // ...
};

This would work:

Compose(Function * f1_ptr, Function * f2_ptr) : _f1(f1_ptr), _f2(f2_ptr)
{    // ^^^  pointers here  ^^^                 ^^^ pointers there ^^^
}

But using raw pointers like this is a problem. Who will be responsible for deleteing them again? Modern C++ avoids such raw pointers wherever possible in favor of so-called smart pointers that do reference counting and automatically delete the pointer when the last reference is destroyed. Therefore, the better design of your class would be like this.

#include <memory>

class Compose : public Function
{

private:

  std::shared_ptr<Function> f1_;
  std::shared_ptr<Function> f2_;

public:

  Compose(std::shared_ptr<Function> f1,
          std::shared_ptr<Function> f2) : f1_ {f1}, f2_ {f2}
  {
  }

  // ...
};

In this case, you don't need to worry about writing a destructor for Compose and it will also be made sure that you'll never dereference an invalid pointer.

You can learn more about resource management using smart pointers here:

Community
  • 1
  • 1
5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • i could write a destructor for Compose that won't be that much of a problem. >our solutio sounds nice, but i don't know if i'll get trouble using this cause i don't really understand it as a whole and if i have to explain it to one of our professors :/ – TheStriker0815 Jan 10 '15 at 20:51
  • Another option would be to read about those techniques and proudly tell your professor what you have learned. I have added some links to my answer that might serve you as a good starting point. – 5gon12eder Jan 10 '15 at 21:02
  • @TheStriker0815 if an exception is thrown during the construction of `Compose` then the destructor will not be called. That's the whole point of using smart pointers like `shared_ptr`. The problem with the way C++ is being taught is, it's still our grand father age old c++ and not the newer standard. – Jagannath Jan 10 '15 at 22:43
  • yeah that'd be a way, but as i was thinking about that a few minutes ago i remembered that we got a restriction at the beginning of our module that we are only allowed to use libraries that are explicitly mentioned on our task sheets :/ But thanks for those links, i'll have a look at them anyway, but that's not a solution i can use :( – TheStriker0815 Jan 10 '15 at 22:48