【问题标题】:using abstract class as data type in constructor of dependent class在依赖类的构造函数中使用抽象类作为数据类型
【发布时间】:2015-03-08 23:29:00
【问题描述】:

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

但是在尝试定义类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" 
..\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)

【问题讨论】:

  • 您似乎不确定Compose 是否管理指向Function 的指针或对Function 的引用。她们不一样。你想要哪个?
  • 我想你的意思一定是Compose(Function * f1, Function * f2):_f1(f1), _f2(f2){}
  • 它必须使用引用进行管理,因为函数类型应该是引用。我只在 Compose 中使用了指针,因为编译器不允许我使用任何其他指针,因为我无法创建函数本身的任何对象,因为它是一个抽象类

标签: c++ class methods types abstract


【解决方案1】:

第一个问题:

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

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

【讨论】:

  • 这行不通,因为不能为函数创建对象,因为它是抽象的:/ 编辑:啊,好吧,我试试我完全忘记了函数的所有变量都必须初始化无论我是否使用它们
  • @TheStriker0815:不完全是。并不是说它们需要被初始化。这是您的父类Function 需要调用它的构造函数。你提供了一个,它需要四个参数。你也可以提供一个不需要参数的。这意味着什么取决于整个程序的逻辑。
  • 好的,结果很好,谢谢!现在唯一的问题是那个引用指针转换的东西
【解决方案2】:

指针和引用可以引用抽象类型。在您的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 编写析构函数,并且还可以确保您永远不会取消引用无效指针。

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

【讨论】:

  • 我可以为 Compose 编写一个析构函数,这不会有太大问题。 >我们的解决方案听起来不错,但我不知道我是否会遇到麻烦,因为我并不真正理解它作为一个整体,如果我必须向我们的一位教授解释它:/
  • 另一种选择是阅读这些技术并自豪地告诉您的教授您学到了什么。我在我的答案中添加了一些链接,可以作为一个很好的起点。
  • @TheStriker0815 如果在Compose 的构造过程中抛出异常,那么析构函数将不会被调用。这就是使用像shared_ptr 这样的智能指针的全部意义所在。教授 C++ 的方式的问题是,它仍然是我们的祖父老 C++,而不是更新的标准。
  • 是的,那是一种方式,但是当我几分钟前想到这一点时,我记得我们在模块的开头有一个限制,即我们只能使用以下库在我们的任务表中明确提到:/但是感谢这些链接,无论如何我都会看看它们,但这不是我可以使用的解决方案:(
猜你喜欢
  • 2020-11-11
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 2016-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多