使用Friend Operators重载模板类中的运算符

时间:2016-11-10 06:10:56

标签: c++ templates visual-studio-2015 operator-overloading friend

考虑以下类Operand:它是一个非常直接的类,因为它接受一个参数并定义了一堆重载操作符,为了简单测试这个类,我选择使用{{1} }类型,因为有分区运算符。如果您注意到某些操作符,则将它们定义为朋友,以便可以在其代码中执行此操作:

修改 有人在评论中询问了什么

float

意思?它是一个重载的运算符,但由于已经为类本身定义了一个成员,因此它被声明为类的朋友,并且在类中定义但不是类成员。这允许用户将两个Operand类实例或对象一起添加,并将新计算的值作为Operand对象返回。我将在inline friend Operand Operand::operator+( const Operand& A, const Operand B ) 部分添加注释,了解正在使用的重载运算符。

snippet

我用4个常见的算术运算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个操作中的每个操作定义了2个朋友运算符。这是类定义。

Operand.h

+-*/

Operand.cpp

#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

我想要做的是模拟这个课程。

所以这里只是定义为类模板的同一个类:

OperandT.h

#include "Operand.h"

const float Operand::ZERO = static_cast<float>(1e-7); 

OperandT.cpp

#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

随着友元操作符注释掉它编译并且类内定义的运算符工作但是当我取消注释类的下半部分时,我最终得到编译器错误。

我遇到的几个问题是:

  • 是否有一种有效的方法来定义朋友操作员或具有类模板的函数?
  • 如果是这样,由于模板的陌生性,适当的语法是什么?
  • 如果没有,有哪些可能的替代方案可以实现相同的功能,以使其尽可能保持通用?
  • 最后但并非最不重要的是,为什么朋友们在头等舱工作得非常好,但是一旦你添加了模板的概念,你最终会遇到火车残骸?

1 个答案:

答案 0 :(得分:0)

在评论部分与$number2 = date('N', $tomorrow);进行简短对话后,他引起了我的注意,我在Danh中实现overloaded friend operators的方式应该被视为错误。是的,它将在Visual Studio以及Visual Studio编译器rextesters.com的这个网站上编译和运行而不会出错。他已经声明实现重载的朋友运营商的正确方法是这样的:

  

正确的方法是visual studio 2013 - 15friend Operand operator+(Operand A, Operand B),我要向MSFT提交错误 - Danh

他还向我展示了未能在GCC或Clang下编译的地方:http://melpon.org

我告诉他我会考虑到这一点而且我做到了。所以我相应地更新了我的friend Operand operator+(const Operand& A, const Operand& B)头文件,它正确编译,构建和运行。 然后我继续修复模板版本,它也正常工作。

以下是更新的类标题。

<强> Operand.h

Operand

<强> OperandT.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 operator+( const Operand& A, const Operand& B ) {
        return Operand( A.getOperand() + B.getOperand() );
    }
    inline friend Operand operator+( const float& value, const Operand& A ) {
        return Operand( value + A.getOperand() );
    }

    inline friend Operand operator-( const Operand& A, const Operand& B ) {
        return Operand( A.getOperand() - B.getOperand() );
    }
    inline friend Operand operator-( const float& value, const Operand& A ) {
        return Operand( value - A.getOperand() );
    }

    inline friend Operand operator*( const Operand& A, const Operand& B ) {
        return Operand( A.getOperand() * B.getOperand() );
    }
    inline friend Operand operator*( const float& value, const Operand& A ) {
        return Operand( value * A.getOperand() );
    }

    inline friend 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 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;
    }    
}; // Operand

//#include "Operand.inl"

#endif // OPERAND_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_; } inline OperandT<T>& operator+=( const T& value ) { operand_ += value; return *this; } inline OperandT<T>& operator-=( const T& value ) { operand_ -= value; return *this; } inline OperandT<T>& operator*=( const T& value ) { operand_ *= value; return *this; } inline OperandT<T>& operator/=( const T& value ) { if ( isZero( value ) ) { operand_ = 0; } else { operand_ /= value; } } inline OperandT<T> operator+() const { return *this; } inline OperandT<T> operator+( const T& value ) const { return OperandT<T>( operand_ + value ); } inline OperandT<T> operator-() const { return OperandT<T>( -operand_ ); } inline OperandT<T> operator-( const T& value ) const { return OperandT<T>( operand_ - value ); } inline OperandT<T> operator*( const T& value ) const { return OperandT<T>( operand_ * value ); } inline OperandT<T> operator/( const T& value ) const { if ( isZero( value ) ) { return OperandT<T>( 0 ); } else { return OperandT<T>( operand_ / value ); } } inline friend OperandT<T> operator+( const OperandT<T>& A, const OperandT<T>& B ) { return OperandT<T>( A.getOperand() + B.getOperand() ); } inline friend OperandT<T> operator+( const float& value, const OperandT<T>& A ) { return OperandT<T>( value + A.getOperand() ); } inline friend OperandT<T> operator-( const OperandT<T>& A, const OperandT<T>& B ) { return OperandT<T>( A.getOperand() - B.getOperand() ); } inline friend OperandT<T> operator-( const float& value, const OperandT<T>& A ) { return OperandT<T>( value - A.getOperand() ); } inline friend OperandT<T> operator*( const OperandT<T>& A, const OperandT<T>& B ) { return OperandT<T>( A.getOperand() * B.getOperand() ); } inline friend OperandT<T> operator*( const float& value, const OperandT<T>& A ) { return OperandT<T>( value * A.getOperand() ); } inline friend 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> 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; } }; // OperandT //#include "OperandT.inl" #endif // OPERAND_T_H