我在使用C ++中的运算符重载实现对数类时遇到了一些问题。
我的第一个目标是如何实施changeBase
方法,我一直很难绕过它。
我试图理解改变对数基数背后的数学,但我无法做到。有人可以向我解释一下吗?
我的第二个目标是能够执行左操作数为double
且右操作数为对数对象的操作。
以下是我的日志类的片段:
// coefficient: double
// base: unsigned int
// result: double
class _log {
double coefficient, result;
unsigned int base;
public:
_log() {
base = 10;
coefficient = 0.0;
result = 0.0;
}
_log operator+ ( const double b ) const;
_log operator* ( const double b ) const;
_log operator- ( const double b ) const;
_log operator/ ( const double b ) const;
_log operator<< ( const _log &b );
double getValue() const;
bool changeBase( unsigned int base );
};
你们真棒,谢谢你的时间。
答案 0 :(得分:5)
我的第二个目标是能够执行左操作数为double且右操作数为对数对象的操作。
为此,您需要将运算符声明为命名空间范围内的非成员函数(即,不在_log
的定义中),例如,
_log operator+(const double a, const _log& b);
如果您需要访问_log
的私人成员,可以在_log
的定义中将其声明为朋友:
friend _log operator+(const double a, const _log& b);
请注意,以下划线开头的名称(例如_log
)保留给全局命名空间中的实现;如果下划线后面跟一个大写字母或另一个下划线,则它随处可见。选择不同的班级名称是个好主意。
答案 1 :(得分:3)
一些事情
17.4.3.2.1全局名称[lib.global.names] 某些名称和功能签名集始终保留给 实现:
- 包含双下划线(_ _)或以...开头的每个名称 下划线后跟一个大写字母 信(2.11)保留给 任何用途的实施。
- 以下划线开头的每个名称都保留给 实现用作名称 全局命名空间。 165
165)这些名称也在namespace :: std(17.4.3.1)中保留。
由于与cmath中的log()冲突,我猜你使用了_log而不是log。出于这个原因,将自己的类保留在标准名称空间中是一个非常糟糕的主意。也许下一版本的标准会提供_log或Logarithm类?
在namespace somename {}
中换行您自己的课程,并使用somename::Logarithm()
正如其他人已经提到的那样你需要声明你的运营商作为朋友重载。而不是你有什么
log operator+ ( const double b ) const;
将其更改为
friend log operator+(const double d, const log& l);
并在命名空间范围内定义函数。
以下是更改基本公式
的数学计算
数学系数表示与日志相乘的部分。所以,如果你有 log_b(x)= y
A是系数,B是基数,Y是结果(或其他一些名称)
答案 2 :(得分:1)
一些想法:
将#2与詹姆斯的建议结合起来:
friend logarithm operator+( const logarithm &l, const logarithm &r );
定义转换构造函数以从float生成logarithm
:
logarithm::logarithm( double f );
现在,C ++会将double
或logarithm
中的1.0 + my_log
转换为my_log + 1.0
。
base
。根据函数定义基本转换:
double alternate_base( double base ) const;
基本转换只是将logarithm
除以备用基数的自然对数。在单个double
中将整数和小数部分一起返回可能是最方便的。