若所有的参数皆需要类型转换——请为此采用non-member函数
若所有的參數皆需要類型轉換——請為此采用non-member函數
經常使用C++的程序猿(希望更多的程序媛),一般不會同意讓classes支持類型轉換,至于為什么,請看后續的博客。假如我們設計一個表示有理數的class,允許”整數隱式轉換為有理數似乎很合理“。首先來一個簡單的實現。
class Rational { public:Rational(int numerator = 0,int denominator = 1; //允許int-to-Rational隱式轉換 int numerator()const;int denominator()const;const Rational operator*(const Rational& rhs)const; //有理數的乘法... };有理數,我們很自然地為他實現了乘法的運算。我們可以輕松地實現兩個有理數相乘,但是,假如我們想要進行混合運算呢?在下面的例子中,2在第一個參數與第二個參數的位置進行隱私類型轉換。
Rational half(1,2); half = half * 2; //1. 通過編譯 half = 2 *half; //2. 無法通過編譯為什么會這樣呢?對于1,編譯器解釋如下,所以很正常地通過了編譯。
operator*(Rational& this,Rational& rhs); //函數的定義部分 //第一個參數是沒辦法改變的,一定是被乘數 half.operator(Rational(2)); //函數的調用部分,2被隱式轉換為了有理數 //與下面的代碼一致 const Rational temp(2); result = half * temp;編譯器拿到2的時候,知道operator*()需要一個Rational,也知道只要調用Rational的構造函數就能夠變出一個適當的Rational,所以,它就做了。
結果就是上面的例子。當然,必須存在non-explicit編譯器才會這么做。
而對于2中的代碼呢,編譯器首先試著如下解釋
2.operator*(half);很明顯,2.operator()是不存在的東西,所以,編譯器會嘗試著尋找一個non-memb operator(),但結果是:沒有找到。所以只能返回一個錯誤。
很明顯,上面對于同一個操作符,卻有了兩種截然不同的結果,你十分抵觸。然后你就會義憤填膺地把構造函數修改為explicit。結果是:兩者一致了,都不支持混合運算。但是,我們的目標不僅僅在于一致性,我們還希望它支持混合運算。那么,請拿出我們的利器:non-member函數。我們暫時允許編譯器執行隱式類型轉換。
class Rational {... }; const Rational operator*(const Rational& lhs,const Rational& rhs); Rational half(1,2); half = half * 2; //通過編譯 half = 2 * half; //通過編譯真的是峰回路轉疑無路,千辛萬苦終于找到可行之道。對于上面的代碼,編譯器會對每個2都轉換為Rational(2)。當你完成了一天的工作后,最后一個要操心的問題是:是否需要一個non-member friend函數?假如否定的,member的對立面不是non-member friend函數。使用了friend,意味著公開自己的所有隱私。這種嚴重破壞自身隱私的可不是好事,可以參考以下的博客太過親密往往不好——用NON-MEMBER,NON-FRIEND替換MEMBER函數還有為了更好更方便地活著——愛上PRIVATE.
總結一下
假如你需要為某個函數的所有參數都進行類型轉化的時候,這個函數必須是non-member。
member的對立面不是non-member friend,請慎用friend。
轉載于:https://www.cnblogs.com/suimeng/p/4887195.html
總結
以上是生活随笔為你收集整理的若所有的参数皆需要类型转换——请为此采用non-member函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二、JavaScript语言--JS基础
- 下一篇: bzoj 1572: [Usaco200