在依赖类的构造函数中使用抽象类作为数据类型

using abstract class as data type in constructor of dependent class

本文关键字:抽象类 数据类型 依赖 构造函数      更新时间:2023-10-16

对于一个大学项目,我们必须创建几个类,所有这些都取决于抽象类函数。

但是在尝试定义类Compose时,它必须组合两个作为构造函数参数传递的不同函数,我遇到了几个问题,如下所示。

在这种情况下,我如何将我的抽象类用作数据类型而没有问题?

抽象类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;}
};

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){}
};

错误消息:

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" 
..srcAufgabe_10_1.cpp: In constructor 'Compose::Compose(Function&, Function&)':
..srcAufgabe_10_1.cpp:37:7: error: cannot convert 'Function' to 'Function*' in assignment
   _f1 = f1;
       ^
..srcAufgabe_10_1.cpp:38:7: error: cannot convert 'Function' to 'Function*' in assignment
   _f2 = f2;
       ^
..srcAufgabe_10_1.cpp: In member function 'virtual double Compose::evaluate(double)':
..srcAufgabe_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)

第一个问题:

一半的错误可以减少到这样:

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

根据您上面显示的内容,这没有任何意义。

第二个问题:

Function没有采用零参数的构造函数。所以你需要在Compose的构造函数中显式调用它的构造函数。也许像这样:

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) {}
};

指针和引用可以引用抽象类型。 在 Compose 类中,您已经声明了指针成员_f1_f2这很好。 但是,不能指定对指针的引用,因此应更改Compose 的构造函数,以便也接受指针作为参数。

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 ^^^
  }
  // ...
};

这将起作用:

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

但是使用这样的原始指针是一个问题。 谁将负责再次delete它们? 现代C++尽可能避免使用此类原始指针,而支持所谓的智能指针,这些指针执行引用计数并在最后一个引用被销毁时自动delete指针。 因此,您的类的更好设计将是这样的。

#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}
  {
  }
  // ...
};

在这种情况下,您无需担心为 Compose编写析构函数,并且还将确保您永远不会取消引用无效指针。

您可以在此处了解有关使用智能指针进行资源管理的更多信息:

  • 维基百科:资源获取是初始化
  • cppreference.com雷伊
  • 堆栈溢出:C++中的 RAII 和智能指针
  • Bjarne Stroustrup:让简单的任务变得简单!(从30:30开始)