Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ constructor, one for degrees, one for radians

What would be the best practice in C++, to define two separate constructors, one having input in degrees whilst the other in radians? The problem I'm having doing it the straight forward way is that the signature of both methods look the same to the compiler, even though the parameter names identify which is which, and the compiler flags a re-declaration error. Is this possible to do without introducing another field?

I can do it using a single constructor by adding an additional bool parameter that would allow selecting which units are being passed, and using an if in the body.

like image 695
gone Avatar asked Jul 20 '17 16:07

gone


2 Answers

Use the named constructor idiom. Make your constructor private, and pick whichever you prefer for the argument type, degrees or radians. Then make appropriately named static member functions which do the necessary conversion.

class Angle {
public:
    static Angle radians(double r) { return Angle(r); }
    static Angle degrees(double d) { return Angle(d / 180.0 * PI); }
private:
    double angle_in_radians;
    Angle(double r) :angle_in_radians(r) {}
};
like image 54
Benjamin Lindley Avatar answered Sep 29 '22 22:09

Benjamin Lindley


What would be the best practice in C++, to define two separate constructors, one having input in degrees whilst the other in radians?

The best practice would be to have only a single constructor that clearly takes only one of them (most probably radians, since all the trigonometrical functions work with radians).

You should have additional functions to convert the values. One way is to use user defined literals1.

These are meant to give plain values a context with a particular unit to use.


I would go the following way:

constexpr long double operator"" _deg ( long double deg )
{
    return deg2rad(deg);
}

long double deg2rad(long double deg) {
    return deg*3.141592/180;
}

long double rad2deg(long double rad) {
    return (rad/3.141592)*180;
}

class Angle {
public:

    /**
     * Default constructor.
     */
    Angle() : radians() {}
    /**
     * Takes the initial angle value as radians.
     */
    Angle(long double rad) : radians(rad) {}

    // Convenience setters and getters
    void rad(long double value) {
        radians = value;
    }
    long double rad() const {
        return radians;
    }
    void deg(long double value) {
        radians = deg2rad(value);
    }
    long double deg() const {
        return rad2deg(radians);
    }
private:
    long double radians; // Only use radians internally
};

int main() {
    Angle ang1(180_deg); // Initialize using the constexpr conversion
    long double deg = 0;
    std::cout << "Enter an angle value in degrees: " << std::flush;
    std::cin >> deg;
    Angle ang2(deg2rad(deg));

}

1The examples from the documentation even have one for converting degrees to radians.

like image 44
user0042 Avatar answered Sep 30 '22 00:09

user0042