因此,您应该能够以 C、K 或 F 的形式输入温度,这将为它们中的每一个调用不同的构造函数。这些构造函数有何不同?
4 回答
假设您使用的是 C++11,您可以使用用户定义的文字来表示一个数字是华氏、开尔文或摄氏度。
如果您不使用 C++11,则始终可以在构造函数中使用枚举类型参数来表达这一点。不过,用户定义的文字方法可能要好得多。
如果您使用温度值的专用数据类型,例如:
struct Celsius { double value; }
struct Kelvin { double value; }
struct Farahemsomething { double value; }
那么你可以只使用简单的重载:
class MyClass
{
public:
MyClass(Celsius temp) { .... = temp.value; ... }
MyClass(Kelvin temp) { .... = temp.value; ... }
...
}
但是,如果您在任何地方都只使用double
所有值,那么您将不得不将构造函数与其他东西区分开来。枚举可能非常有用,但您将在同一个构造函数中使用它,并且必须切换枚举值:
enum TemperatureUnits
{ Celsius,Kelvin, Farahemsomething };
class MyClass
{
public:
MyClass(TemperatureUnits unit, double value) {
if(unit == Celsius)
{ ... }
else if(unit == ....
...
...
}
}
您还可以将“空心类型”与原始双精度混合以人为地启用重载,但这会变得很棘手:
struct Celsius { }
struct Kelvin { }
struct Farahemsomething { }
class MyClass
{
public:
MyClass(Celsius unit, double value) { .... = value; ... }
MyClass(Kelvin unit, double value) { .... = value; ... }
...
}
在这里,请注意“unit”只是一个空结构,允许您选择正确的重载,因此您使用简单的空“Celsius”调用构造函数,后跟 234.55 值。
编辑:我又一次忘记了 C11 的特性。AnotherTest 关于自定义文字的建议可能是最简单的。
我知道我对此有点晚了,但这是我想出的:
#include <iostream>
namespace units {
template<int> struct temp_unit { };
typedef temp_unit<1> celcius;
typedef temp_unit<2> fahrenheit;
typedef temp_unit<3> kelvin;
typedef temp_unit<4> reaumur;
typedef temp_unit<5> rankine;
}
namespace priv {
struct converter_impl {
virtual ~converter_impl() { }
virtual float to_celcius() const = 0;
virtual float to_fahrenheit() const = 0;
virtual float to_kelvin() const = 0;
virtual float to_reaumur() const = 0;
virtual float to_rankine() const = 0;
};
struct from_celcius : converter_impl {
protected:
float m_value;
public:
from_celcius(float v) : m_value(v) { }
float to_celcius() const { return m_value; }
float to_fahrenheit() const { return (m_value * 1.8) + 32; }
float to_kelvin() const { return (m_value + 273.15); }
float to_reaumur() const { return (m_value * 0.8); }
float to_rankine() const { return (m_value * 1.8 +32 + 459.67); }
};
struct from_fahrenheit : converter_impl {
protected:
float m_value;
public:
from_fahrenheit(float v) : m_value(v) { }
float to_celcius() const { return ((m_value - 32) / 1.8); }
float to_fahrenheit() const { return m_value; }
float to_kelvin() const { return ((m_value + 459.67) / 1.8); }
float to_reaumur() const { return ((m_value - 32) / 2.25); }
float to_rankine() const { return (m_value + 459.67); }
};
struct from_kelvin : converter_impl {
protected:
float m_value;
public:
from_kelvin(float v) : m_value(v) { }
float to_celcius() const { return (m_value - 273.15); }
float to_fahrenheit() const { return ((m_value * 1.8) - 459.67); }
float to_kelvin() const { return m_value; }
float to_reaumur() const { return ((m_value - 273.15) * 0.8); }
float to_rankine() const { return (m_value * 1.8); }
};
struct from_reaumur : converter_impl {
protected:
float m_value;
public:
from_reaumur(float v) : m_value(v) { }
float to_celcius() const { return (m_value * 1.25); }
float to_fahrenheit() const { return ((m_value * 2.25) + 32); }
float to_kelvin() const { return ((m_value * 1.25) + 273.15); }
float to_reaumur() const { return m_value; }
float to_rankine() const { return ((m_value * 2.25) + 32 + 459.67); }
};
struct from_rankine : converter_impl {
protected:
float m_value;
public:
from_rankine(float v) : m_value(v) { }
float to_celcius() const { return ((m_value - 32 - 459.67) / 1.8); }
float to_fahrenheit() const { return (m_value - 459.67); }
float to_kelvin() const { return (m_value / 1.8); }
float to_reaumur() const { return ((m_value - 32 - 459.67) / 2.25); }
float to_rankine() const { return m_value; }
};
}
struct temp_converter {
protected:
priv::converter_impl * m_impl;
public:
temp_converter(float value, units::celcius) : m_impl(new priv::from_celcius(value)) { }
temp_converter(float value, units::fahrenheit) : m_impl(new priv::from_fahrenheit(value)) { }
temp_converter(float value, units::kelvin) : m_impl(new priv::from_kelvin(value)) { }
temp_converter(float value, units::reaumur) : m_impl(new priv::from_reaumur(value)) { }
temp_converter(float value, units::rankine) : m_impl(new priv::from_rankine(value)) { }
~temp_converter() { delete m_impl; }
float to_celcius() const { return m_impl->to_celcius(); }
float to_fahrenheit() const { return m_impl->to_fahrenheit(); }
float to_kelvin() const { return m_impl->to_kelvin(); }
float to_reaumur() const { return m_impl->to_reaumur(); }
float to_rankine() const { return m_impl->to_rankine(); }
inline float as(units::celcius) const { return to_celcius(); }
inline float as(units::fahrenheit) const { return to_fahrenheit(); }
inline float as(units::kelvin) const { return to_kelvin(); }
inline float as(units::reaumur) const { return to_reaumur(); }
inline float as(units::rankine) const { return to_rankine(); }
};
int main(int argc, char ** argv) {
temp_converter tc(-31, units::reaumur());
std::cout << "Celcius: " << tc.to_celcius() << std::endl;
std::cout << "Fahrenheit: " << tc.to_fahrenheit() << std::endl;
std::cout << "Kelvin: " << tc.to_kelvin() << std::endl;
std::cout << "Réaumur: " << tc.to_reaumur() << std::endl;
std::cout << "Rankine: " << tc.to_rankine() << std::endl;
return 0;
}
我知道您只问如何区分单位,但我在编写示例时被带走了。
有很多方法可以实现这一点,您可以在构造函数参数中使用枚举指定单位 - 具有单个构造函数的解决方案。在这种情况下,您将传递一个原始数字,而枚举定义了如何解释其值。
如果您真的需要不同的构造函数,您可以指定自己的摄氏温度、华氏温度和开尔文类型并将它们传递给不同的构造函数。
struct Fahrenheit {
Fahrenheit (double d = 0) : t(d) {}
double t;
};
struct Celsius {
Celsius(double d = 0) : t(d) {}
double t;
};
struct Kelvin {
Kelvin(double d = 0) : t(d) {}
double t;
};
class Temperature {
public:
Temperature(Fahrenheit f) {
temperature.t = (f.t + 459.67) * 5 / 9;
cout << "Fahrenheit constructor" << endl;
}
Temperature(Celsius c) {
temperature.t = c.t + 273.15;
cout << "Celsius constructor" << endl;
}
Temperature(Kelvin k) : temperature(k) {
cout << "Kelvin constructor" << endl;
}
double getTemperature() {
return temperature.t;
}
private:
Kelvin temperature;
};
主要是:
Temperature t1(Kelvin(50)), t2(Fahrenheit (90)), t3(Celsius(23));
cout << t1.getTemperature() << " " << t2.getTemperature() << " " << t3.getTemperature() << endl;
输出:
Kelvin constructor
Fahrenheit constructor
Celsius constructor
50 305.372 296.15
该类将在内部将温度存储为开尔文(最科学的 IMO),并将其他单位转换为开尔文。