C++是实现一系列不同实现的最佳方式

C++ - best way to do an array of different implementations

本文关键字:实现 最佳 方式 一系列 C++      更新时间:2023-10-16

我正在尝试实践OO设计。我制作了以下类,最终让用户从列表中选择一种温度单位类型(如fahrenheit(,并将摄氏温度转换为他们选择的温度:

温度单位.h:

#include "fahrenheittemperatureunit.h"
#include "kelvintemperatureunit.h"
#include "temperatureunit.h"
#include <list>
class TemperatureUnits
{
public:
    static std::list<TemperatureUnit> All();
    const static FahrenheitTemperatureUnit kFahrenheit;
    const static KelvinTemperatureUnit kKelvin;
};

TemperatureUnits.cp:

#include "temperatureunits.h"
std::list<TemperatureUnit> TemperatureUnits::All()
{
    std::list<TemperatureUnit> units;
    units.push_back(TemperatureUnits::kFahrenheit);
    units.push_back(TemperatureUnits::kKelvin);
    return units;
}
const KelvinTemperatureUnit TemperatureUnits::kKelvin;
const FahrenheitTemperatureUnit TemperatureUnits::kFahrenheit;

温度单位:h

class TemperatureUnit
{
public:
    explicit TemperatureUnit(const std::string &name);
    virtual ~TemperatureUnit() {}
    const std::string& Name() const;
    virtual float FromCelcius(float celcius) const {return 0;}
private:
    std::string name_;
};

温度单位.cpp:

#include "temperatureunit.h"
TemperatureUnit::TemperatureUnit(const std::string &name)
    :
    name_(name)
{
}
const std::string& TemperatureUnit::Name() const
{
    return name_;
}

最后,一个例子子类:

Kelvin温度单位:h:

#include "temperatureunit.h"
class KelvinTemperatureUnit : public TemperatureUnit
{
public:
    explicit KelvinTemperatureUnit();
    virtual float FromCelcius(float celcius) const;
};

Kelvin温度单位.cpp:

#include "kelvintemperatureunit.h"
KelvinTemperatureUnit::KelvinTemperatureUnit()
    :
    TemperatureUnit(std::string("Kelvin"))
{
}
float KelvinTemperatureUnit::FromCelcius(float celcius) const
{
    return celcius - 273;
}

上面有很多缺陷(据我所知(:

  • 我不确定class TemperatureUnits{ ... static std::list<TemperatureUnit> All();模式是正确的,但不确定什么会更好。

  • 通过将温度单位的类型存储在std::列表中,它们被视为基类温度单位,而不是像KelvinTemperatureUnit那样的专业。这意味着调用FromCelcius方法无法正常工作。我很确定我以前用Java做过这种事情。

  • 我尝试过,但它可能很难看,会冒犯别人:(

有人对解决这个问题的最佳方法有什么想法吗?

谢谢!

您在Java中所做的工作之所以有效,是因为在Java中,所有调用都是virtualstatic,并且使用指针而不是副本来传递对象。而C++中的情况并非如此。

这是因为vtable没有复制到All()方法的基类中。因此,您需要存储需要C++0x编译器的右值引用,或者只传递基类的指针。所需更改如下:

static std::list<TemperatureUnit*> All():

实施方式为:

std::list<TemperatureUnit*> TemperatureUnits::All()
{
    std::list<TemperatureUnit*> units;
    units.push_back(&TemperatureUnits::kFahrenheit);
    units.push_back(&TemperatureUnits::kKelvin);
    return units;
}
I am pretty sure I used to do this type of thing using Java.

Java对象是引用。C++对象是值。只需转换为引用,就可以获得更多等效代码。哦,Java list就是C++vector。C++list是一个链表。

很简单,不必费力地将任何Java知识传授给C++,它们是截然不同的语言,您应该从头开始使用C++。值得编写的C++看起来与Java截然不同。

int main() {
    std::vector<TemperatureUnit*> units;
    FahrenheitTemperatureUnit kFahrenheit;
    KelvinTemperatureUnit kKelvin;
    units.push_back(&kFahrenheit);
    units.push_back(&kKelvin);
    // Do something here
}

TemperatureUnit的容器应该是TemperatureUnit*的容器。在前一种情况下,您有一个非专用实例的容器,而后者是接口

Java和C++之间的区别

我不确定这里的目标是什么,但为什么不只是一个温度类?

class Temperature {
public:
  enum class TemperatureUnit {
    KELVIN,
    CELCIUS
  }
  Temperature( double value, TemperatureUnit unit );
  void set_value( double value, TemperatureUnit unit );
  double value( TemperatureUnit unit ) const;
private:
  double value_; // Always stored internally as KELVIN
};