2016-11-10 225 views
-1

請考慮以下類Operand:它是一個非常直接的類,因爲它接受單個Parameter並定義一堆重載操作符,並且爲了簡化此類的測試,我選擇使用float類型,因爲有分裂運營商。如果你與一些運營商的注意,他們被定義爲這樣的朋友,一個是能夠做到這一點在他們的代碼:在評論模板類與朋友操作符重載操作符

編輯 有人問是什麼

inline friend Operand Operand::operator+(const Operand& A, const Operand B) 

是什麼意思?它是一個重載操作符,但由於已經爲類本身定義了一個成員,所以它被聲明爲類的一個朋友,並且在類中定義,但不是類成員。這允許用戶將兩個操作數類實例或對象添加到一起,並將新計算的值作爲操作數對象返回。我將爲snippet部分添加註釋,以瞭解正在使用哪些重載操作符。

片斷

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個朋友運營商完成這是對每個4個操作的定義。這是類定義。

Operand.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 

Operand.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)); 

帶有註釋的朋友運營商它編譯和類定義的運算符工作,但是當我取消註釋時我最終得到編譯器錯誤。

,我已經是幾個問題:

  • 是否有定義的朋友運算符或函數與類模板的有效方法是什麼?
  • 如果是這樣,由於模板的奇怪性,什麼是合適的語法?
  • 如果不是,那麼可能有哪些替代方案可以實現相同的功能以儘可能保持通用?
  • 最後但並非最不重要的是,爲什麼朋友們在第一堂課中工作得很好,但是一旦您添加模板概念,您最終會遇到火車殘骸?
+0

是什麼'在線的朋友操作數操作數::運算符+(常量操作數&A,常量操作數B)'是什麼意思? – Danh

+0

@Danh添加到操作數對象一起查看代碼頂部的代碼片斷部分。由於這是一個類對象,因此類定義的運算符會執行類instance + value,其中兩個朋友的值爲+ class實例,而您詢問的是class instance +另一個類實例。 –

+0

你測試過了嗎?我不認爲它會起作用 – Danh

回答

0

在評論部分,他帶來了我的注意,我是能夠實現的方式overloaded friend operatorsvisual studio 2013 - 15應該被認爲是一個錯誤具有Danh簡短的交談之後。是的,它將在Visual Studio以及Visual Studio編譯器rextesters.com的這個網站上編譯和運行,沒有錯誤。他指出,實施重載朋友經營的正確方法是這樣的:

正確的方法是friend Operand operator+(Operand A, Operand B)friend Operand operator+(const Operand& A, const Operand& B),我將文件複製到MSFT錯誤 - DANH

他還指給我看它未能從這裏下GCC或Clang的編譯:http://melpon.org

我告訴他,我會考慮到這一點和我做到了。所以我相應地更新了我的Operand頭文件,它編譯,構建並正確運行。 然後我繼續並修復了模板版本,它也正常工作。

這是更新的類標題。

Operand.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 

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_; 
    } 

    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 

現在我的代碼工作正常使用模板一切都要感謝Danh