Visual Как я могу сделать разные конструкторы для разных единиц температуры в C ++?

Таким образом, вы должны иметь возможность вводить температуру в C, K или F, которая будет вызывать разные конструкторы для каждого из них. Чем отличаются эти конструкторы?

1

Решение

Если вы используете выделенные типы данных для значение температуры, как:

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 == ....
...
...
}
}

Вы также можете смешивать «пустые типы» с необработанным double, чтобы искусственно разрешить использование перегрузок, но это становится сложнее:

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 о пользовательских литералах, вероятно, самый простой.

3

Другие решения

Предполагая, что вы используете C ++ 11, вы можете использовать пользовательские литералы, чтобы выразить, что число в градусах Фаренгейта, Кельвина или Цельсия.

Если вы не используете C ++ 11, у вас всегда может быть параметр типа enum для вашего конструктора, который выражает это. Пользовательский буквальный подход, вероятно, намного лучше, хотя.

7

Я знаю, что немного опоздал с этим, но вот что я придумал:

#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;
}

Я знаю, что вы только спрашивали, как провести различие между единицами, но я увлекся, когда кодировал пример.

2

Есть много способов достичь этого, вы можете указать единицу измерения с помощью enum в параметре конструктора — решение с одним конструктором. В этом случае вы будете передавать примитивное число, а перечисление определяет, как его значение интерпретируется.

Если вам действительно нужны разные конструкторы, вы можете указать свои собственные типы Цельсия, Фаренгейта и Кельвина и передать их различным конструкторам.

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

Класс будет хранить внутреннюю температуру как Кельвин (большинство научных ИМО) и будет преобразовывать другие единицы в Кельвин.

0
По вопросам рекламы [email protected]