1

したがって、C、K、または F で温度を入力できるはずであり、それぞれに対して異なるコンストラクターが呼び出されます。これらのコンストラクターはどのように異なりますか?

4

4 に答える 4

7

C++11 を使用していると仮定すると、ユーザー定義のリテラルを使用して、数値が華氏、ケルビン、または摂氏であることを表すことができます。

C++11 を使用していない場合は、これを表現するコンストラクターに enum 型パラメーターをいつでも使用できます。ただし、ユーザー定義のリテラル アプローチの方がおそらくはるかに優れています。

于 2013-03-10T11:55:41.430 に答える
3

次のように、温度のに専用のデータ型を使用する場合:

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

ここで、「ユニット」は正しいオーバーロードを選択できる単なる空の構造体であるため、単純な空の「摂氏」の後に 234.55 の値を指定してコンストラクターを呼び出すことに注意してください。

EDIT:そしてまたC11の機能を忘れていました..カスタムリテラルに関するAnotherTestの提案はおそらく最も簡単です。

于 2013-03-10T11:59:11.470 に答える
2

私はこれに少し遅れていることを知っていますが、ここに私が思いついたものがあります:

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

単位を区別する方法だけを尋ねられたことは知っていますが、例をコーディングしているときに夢中になりました。

于 2013-03-10T13:26:39.207 に答える
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) として内部的に保存し、他の単位をケルビンに変換します。

于 2013-03-10T11:56:09.310 に答える