我需要代表Volts,Ampers和Watts及其关系(例如W = V * I)..
这就是我的意思,但看起来真的很冗长。有关如何使其更简洁的任何想法?
#include <stdio.h>
#include <iostream>
template<class T>
class double_val {
public:
explicit double_val(double val):_val(val) { };
double_val(const T& other) {
_val = other._val;
}
T& operator=(const T &other) {
_val = other._val;
return *this;
}
T operator+ (const T& other) const {
return T(this->_val + other._val);
}
T operator+ (double val) const {
return T(this->_val + val);
}
T operator- (const T& other) const {
return T(this->_val - other._val);
}
T operator- (double val) const {
return T(this->_val - val);
}
T operator* (const T& other) const {
return T(this->_val * other._val);
}
T operator* (double val) const {
return T(this->_val * val);
}
T operator/ (const T& other) const {
return T(this->_val / other._val);
}
T operator/ (double val) const {
return T(this->_val / val);
}
bool operator== (const T& other) const{
return this->_val == other._val;
}
bool operator!= (const T& other) const{
return this->_val != other._val;
}
bool operator > (const T& other) const{
return this->_val > other._val;
}
bool operator >= (const T& other) const{
return this->_val >= other._val;
}
bool operator < (const T& other) const{
return this->_val < other._val;
}
bool operator <= (const T& other) const{
return this->_val <= other._val;
}
void val(double val){
_val = val;
}
double val() const {
return _val ;
}
virtual const char* name() const = 0;
private:
double _val;
};
template<class T>
std::ostream& operator<<(std::ostream &os, const double_val<T> &t) {
return os << t.val() << " " << t.name();
}
class Amper:public double_val<Amper> {
public:
Amper(double val):double_val<Amper>(val) {}
const char* name() const {
return "Amper";
}
};
class Volt:public double_val<Volt> {
public:
Volt(double val):double_val<Volt>(val) {}
const char* name() const {
return "Volt";
}
};
class Watt:public double_val<Watt> {
public:
Watt(double val):double_val<Watt>(val) {}
const char* name() const {
return "Watt";
}
};
// Watt = I * V
Watt operator* (const Volt &v, const Amper& a) {
return Watt(a.val() * v.val());
}
Watt operator* (const Amper &a, const Volt& v) {
return Watt(a.val() * v.val());
}
// Volts = Watts/Ampers
Volt operator / (const Watt &w, const Amper& a) {
return Volt(w.val() / a.val());
}
// Ampers = Watts/Volts
Amper operator / (const Watt &w, const Volt& v) {
return Amper(w.val() / v.val());
}
int main(int argc, char **argv) {
using namespace std;
Watt w = Volt(66) * Amper(7);
Amper a = w / (Volt(646) * Volt(444));
cout << a << endl;
return 0;
}
(注意:我故意省略了operator double(),因为我想避免像Volt(4)+ Watt(6)这样的禁止操作
答案 0 :(得分:10)
在库形式中确实有一种不那么冗长的方式, Boost.Units ,它将SI单位定义为类型安全类模板实例化。
答案 1 :(得分:3)
Boost.Units
是一个很好的解决方案,可以满足您的需求,因为它提供了伏特,安培,瓦特和开箱即用的适当操作符的代表。
Boost.Operators
针对非SI单位的自定义数字类型的一般情况解决了这个问题。
答案 2 :(得分:2)
如果客户端代码合作,您可以使用std::rel_ops删除逻辑操作。 rel_ops
根据您的==和&lt;来定义一堆逻辑运算符。运算符。
然而这是有问题的 - 它强制客户端使用rel_ops,而rel_ops突然允许任何具有==和&lt;的类。运算符与所有其他运算符进行比较。这可能不是你想要的。
IMO更好的选择是使用boost operators库,它似乎是数值类型的理想选择,因为它提供了数字类型所需的所有各种运算符。您只需定义一些基本运算符,然后根据您的规范填写其余运算符。从boost文档的示例中窃取:
template <class T>
class point // note: private inheritance is OK here!
: boost::addable< point<T> // point + point
, boost::subtractable< point<T> // point - point
, boost::dividable2< point<T>, T // point / T
, boost::multipliable2< point<T>, T // point * T, T * point
> > > >
{
public:
point(T, T);
T x() const;
T y() const;
point operator+=(const point&);
// point operator+(point, const point&) automatically
// generated by addable.
point operator-=(const point&);
// point operator-(point, const point&) automatically
// generated by subtractable.
point operator*=(T);
// point operator*(point, const T&) and
// point operator*(const T&, point) auto-generated
// by multipliable.
point operator/=(T);
// point operator/(point, const T&) auto-generated
// by dividable.
private:
T x_;
T y_;
};
答案 3 :(得分:2)
此外,Boost Utility包含的设施可以极大地简化在这种情况下编写所有操作员管道。
我最近在这里做了一个示例:Can you set a maximum limit to an integer (C++)?