我在创建另一个类的扩展解析器时遇到问题。
这是我所拥有的示意图

#include <iostream>

class HeaderType{
public:
  HeaderType(){ this->value1 = 0; }
  double getValue1(){return this->value1;}
  void setValue1(double v){ this->value1 = v; }
protected:
  double value1;
};

class Parser{
public:
  Parser() { this->header = new HeaderType(); }
  virtual ~Parser() {};

  virtual void Parse(){ this->header->setValue1(10); }
  HeaderType* getHeader(){return this->header;}

protected:
  HeaderType* header;
};

class ExtendedHeaderType : public HeaderType{
public:
  ExtendedHeaderType(){ this->value2 = 0; }
  double getValue2(){return this->value2;}
  void setValue2(double v){ this->value2 = v; }
protected:
  double value2;
};

class ExtendedParser : public Parser{
public:
  ExtendedParser() : Parser() { this->header = new ExtendedHeaderType(); }
  virtual ~ExtendedParser(){ delete this->header; }
  ExtendedHeaderType* getHeader(){return this->header;}
  virtual void Parse(){ Parser::Parse(); this->header->setValue2(20); }
protected:
  ExtendedHeaderType* header;
};

int main()
{
  ExtendedParser* parser = new ExtendedParser();
  parser->Parse();
  ExtendedHeaderType* header = parser->getHeader();
  double value = header->getValue1();

  std::cerr << "Value: " << value << std::endl;

  return 0;
}


但是,当我这样做时,getValue1()总是返回0,我真的不明白为什么。
当我执行parser-> Parse()时,它应该调用Parser :: Parse(),将value1设置为10,而当我执行getValue1()时,它应该返回10,而不是0。
我真的不明白为什么会这样。

谢谢。

编辑:当我使用此代码并在主体中调用header-> getValue1()时,它返回0,但是调用header-> getValue2()返回20(按预期)。

编辑2:实际上,我认为我想做的事情是不可能的(或者至少不是干净的)。我认为我必须创建一个HeaderType和ExtendedHeaderType,但这不是HeaderType的派生类,并在ExtendedParser中创建每个实例。
IMO最好能够“扩展”一个类,但我认为在内存方面比较困难,因为先分配基类,然后再分配派生类,但是派生类很难修改数据基类的类型,因为它将需要不同数量的内存。

最佳答案

继承不能重新定义字段以更改其类型-因此,您的代码本质上是创建一个具有两个字段的ExtendedParser类:


类型为HeaderType *的Parser :: header
类型为ExtendedHeaderType *的ExtendedParser :: header


您在value1中获得0的原因是因为ExtendedParser中的Parse在基类上调用了Parse,该基类更新了Parser :: header的value1。然后,它在ExtendedParser :: header中更新value2。

然后,您调用getHeader,它返回ExtendedParser :: header,实际上,它的value1字段从未被触摸过,因此得到0。

有几种方法可以实现我认为您想做的事情。一种方法是不要在ExtendedParser中重新定义标头,但必须将标头下调到ExtendedParser :: Parse中的ExtendedHeaderType。另一种方法是对Parser和HeaderType使用合成而不是继承(请参见decorator设计模式)。

09-09 18:48