【发布时间】:2016-11-10 06:10:56
【问题描述】:
考虑下面这个类Operand:它是一个非常直接的类,因为它接受一个参数并定义了一堆重载运算符,为了简化测试这个类,我选择使用float 类型,因为那里是除法运算符。如果您注意到某些操作员被定义为朋友,以便能够在他们的代码中执行此操作:
编辑 有人在cmets里问什么
inline friend Operand Operand::operator+( const Operand& A, const Operand B )
是什么意思?它是一个重载运算符,但由于已经为类本身定义了一个成员作为成员,所以它被声明为类的朋友,并且在类中定义但不是类成员。这允许用户将两个 Operand 类实例或对象添加在一起,并将新计算的值作为 Operand 对象返回。我会将 cmets 添加到 snippet 部分,以了解正在使用哪些重载运算符。
sn-p
Operand A( 2.3f );
Operand B( 4.5f );
Operand C( 0 );
Operand D( 0 );
C = A + B; // inline friend Operand Operand::operator+( const Operand& A, const Operand B );
D = C + 2.5f; // Overloaded Operator Defined as Class Member
D = 3.4f + B; // inline friend Operand Operand::operator+( const Value& value, const Operand A );
我已经使用 4 种常见的算术运算 +-*/ 完成了这项工作,其中一个运算符在类中定义为成员,并为 4 个运算中的每一个定义了 2 个友元运算符。这是类定义。
操作数.h
#ifndef OPERAND_H
#define OPERAND_H
class Operand {
public:
static const float ZERO;
protected:
float operand_;
public:
explicit Operand( float a = float() ) : operand_( a ) {}
inline float getOperand() const {
return operand_;
}
inline Operand& operator+=( const float& value ) {
operand_ += value;
return *this;
}
inline Operand& operator-=( const float& value ) {
operand_ -= value;
return *this;
}
inline Operand& operator*=( const float& value ) {
operand_ *= value;
return *this;
}
inline Operand& operator/=( const float& value ) {
if ( isZero( value ) ) {
operand_ = 0;
} else {
operand_ /= value;
}
}
inline Operand operator+() const { // Unary
return *this;
}
inline Operand operator+( const float& value ) const {
return Operand( operand_ + value );
}
inline Operand operator-() const { // Unary
return Operand( -operand_ );
}
inline Operand operator-( const float& value ) const {
return Operand( operand_ - value );
}
inline Operand operator*( const float& value ) const {
return Operand( operand_ * value );
}
inline Operand operator/( const float& value ) const {
if ( isZero( value ) ) {
return Operand( 0 );
} else {
return Operand( operand_ / value );
}
}
inline friend Operand Operand::operator+( const Operand& A, const Operand B ) {
return Operand( A.getOperand() + B.getOperand() );
}
inline friend Operand Operand::operator+( const float& value, Operand A ) {
return Operand( value + A.getOperand() );
}
inline friend Operand Operand::operator-( const Operand& A, const Operand B ) {
return Operand( A.getOperand() - B.getOperand() );
}
inline friend Operand Operand::operator-( const float& value, Operand A ) {
return Operand( value - A.getOperand() );
}
inline friend Operand Operand::operator*( const Operand& A, const Operand B ) {
return Operand( A.getOperand() * B.getOperand() );
}
inline friend Operand Operand::operator*( const float& value, const Operand A ) {
return Operand( value * A.getOperand() );
}
inline friend Operand Operand::operator/( const Operand& A, const Operand B ) {
if ( isZero( B.getOperand() ) ) {
return Operand( 0 );
} else {
return Operand( A.getOperand() / B.getOperand() );
}
}
inline friend Operand Operand::operator/( const float& value, const Operand A ) {
if ( isZero( A.getOperand() ) ) {
return Operand( 0 );
} else {
return Operand( value / A.getOperand() );
}
}
inline static bool isZero( float value ) {
if ( (value > -ZERO) && (value < ZERO) ) {
return true;
}
return false;
} // isZero
}; // Operand
// #include "Operand.inl"
#endif // OPERAND_H
操作数.cpp
#include "Operand.h"
const float Operand::ZERO = static_cast<float>(1e-7);
我想要做的是模板这个类。
所以这里只是定义为类模板的同一个类:
OperandT.h
#ifndef OPERAND_T_H
#define OPERAND_T_H
template <typename T>
class OperandT {
public:
static const T ZERO;
protected:
T operand_;
public:
explicit OperandT<T>( T a = T() ) : operand_( a ) {}
inline T getOperand() const {
return operand_;
} // getOperand
inline OperandT<T>& operator+=( const T& value ) {
operand_ += value;
return *this;
} // operator+=
inline OperandT<T>& operator-=( const T& value ) {
operand_ -= value;
return *this;
} // operator-=
inline OperandT<T>& operator*=( const T& value ) {
operand_ *= value;
return *this;
} // operator*=
inline OperandT<T>& operator/=( const T& value ) {
if ( isZero( value ) ) {
operand_ = 0;
} else {
operand_ /= value;
}
} // operator/=
inline OperandT<T> operator+() const {
return *this;
} // operator+ Unary
inline OperandT<T> operator+( const T& value ) const {
return OperandT<T>( operand_ + value );
} // operator+ Binary
inline OperandT<T> operator-() const {
return OperandT<T>( -operand_ );
} // operator- Unary (Negate Value)
inline OperandT<T> operator-( const T& value ) const {
return OperandT<T>( operand_ - value );
} // opeator- Binary (Subtraction)
inline OperandT<T> operator*( const T& value ) const {
return OperandT<T>( operand_ * value );
} // operator* Post Multiply
inline OperandT<T> operator/( const T& value ) const {
if ( isZero( value ) ) {
return OperandT<T>( 0 );
} else {
return OperandT<T>( operand_ / value );
}
} // operator/ Post Divide
/*/ Having Trouble With Operators When Using Templates and Friends
inline friend OperandT<T> OperandT<T>::operator+( const OperandT<T>& A, const OperandT<T> B ) {
return OperandT<T>( A.getOperand() + B.getOperand() );
}
inline friend OperandT<T> OperandT<T>::operator+( const float& value, OperandT<T> A ) {
return OperandT<T>( value + A.getOperand() );
}
inline friend OperandT<T> OperandT<T>::operator-( const OperandT<T>& A, const OperandT<T> B ) {
return OperandT<T>( A.getOperand() - B.getOperand() );
}
inline friend OperandT<T> OperandT<T>::operator-( const float& value, OperandT<T> A ) {
return OperandT<T>( value - A.getOperand() );
}
inline friend OperandT<T> OperandT<T>::operator*( const OperandT<T>& A, const OperandT<T> B ) {
return OperandT<T>( A.getOperand() * B.getOperand() );
}
inline friend OperandT<T> OperandT<T>::operator*( const float& value, const OperandT<T> A ) {
return OperandT<T>( value * A.getOperand() );
}
inline friend OperandT<T> OperandT<T>::operator/( const OperandT<T>& A, const OperandT<T> B ) {
if ( isZero( B.getOperand() ) ) {
return OperandT<T>( 0 );
} else {
return OperandT<T>( A.getOperand() / B.getOperand() );
}
}
inline friend OperandT<T> OperandT<T>::operator/( const float& value, const OperandT<T> A ) {
if ( isZero( A.getOperand() ) ) {
return OperandT<T>( 0 );
} else {
return OperandT<T>( value / A.getOperand() );
}
} */
inline static bool isZero( T value ) {
if ( (value > -ZERO) && (value < ZERO) ) {
return true;
}
return false;
} // isZero
}; // OperandT
#include "OperandT.inl"
#endif // OPERAND_T_H
OperandT.cpp
#include "OperandT.h"
template <typename T>
const T OperandT<T>::ZERO = static_cast<T>( static_cast<float>(1e-7) );
将友元运算符注释掉后,它可以编译,并且类中定义的运算符可以工作,但是当我取消注释类的下部时,我最终会遇到编译器错误。
我的几个问题是:
- 是否有一种有效的方法来使用类模板定义友元运算符或函数?
- 如果是这样,由于模板的陌生性,合适的语法是什么?
- 如果不是,有哪些可能的替代方法来实现相同的功能以尽可能保持通用性?
- 最后但并非最不重要的一点是,为什么朋友们在头等舱工作得很好,但是一旦添加了模板的概念,您最终会遇到火车事故?
【问题讨论】:
-
inline friend Operand Operand::operator+( const Operand& A, const Operand B )是什么意思? -
@Danh 添加到操作数对象一起查看顶部代码的 sn-p 部分。由于这是一个类对象,类定义运算符是类实例+值,其中两个朋友是值+类实例,而您要问的一个是类实例+另一个类实例。
-
你测试了吗?我认为它不会起作用
-
正确的方法是
friend Operand operator+(Operand A, Operand B)或friend Operand operator+(const Operand& A, const Operand& B),我要向MSFT 提交错误 -
那就是编译器的bug
标签: c++ templates visual-studio-2015 operator-overloading friend