C++中的友元模版

友元在C++中意味著不好的設(shè)計,因忽略訪問屬性的限制,破壞了封裝性。我卻很喜歡這個特性。
特別說明,這個特性適合庫作者,一般的使用者可能意義不大,尤其是作為代碼的搬運工。
在非模版的設(shè)計中,有些時候,在寫目標類的時候尚不能確定那個類成為友元類,只能后期增加友元類的聲明,這就導(dǎo)致目標類的代碼不能封閉。模版可以解決這個問題,將友元類的設(shè)置延后到編譯階段。
比如有個日志類,有私有的方法和私有數(shù)據(jù)成員。想要直接訪問私有數(shù)據(jù)成員,除了用公開的get/set外,就只能用友元了。通過模版,這個myLog類的代碼就能封閉了。

template<typename T> 
class myLog
{
    friend T;
    std::string str;
    void print()
    {
        std::cout << str << std::endl;
    }
public:
    myLog() = default;
};
class writeDataToLog
{
private:
    using Log = myLog<writeDataToLog>;
    Log _log;
public:
    void setval(std::string data) {
        _log.str = data;
    }
    void print()
    {
        _log.print();
    }
};

重要的就是friend T;這一句,在writeDataToLog里就可以直接變身為myLog的友元,調(diào)用私有的變量和函數(shù)。
如果T是普通類型如int,double等,這一句是被編譯器忽略的,不會有副作用。所以如果定義一個別名來直接使用類型無關(guān)的myLog:

using myLog_t = myLog<void>;
myLog_t log;

如果還不能說明友元模版的必要性,我們看看另外一個例子(重點在第14行),這是個使用引用計數(shù)的智能指針的片段:

template<typename T>
class SmartPointer
{
   T* pointer = nullptr;
   ReferenceCount* refcount = nullptr;
  //友元模板,讓其它類型的智能指針可以直接訪問私有變量
  template<typename>
  friend class SmartPointer;
  //...     
  //有繼承關(guān)系的構(gòu)造,向上轉(zhuǎn)換,U繼承自T
  template<typename U, typename = std::enable_if_t<std::is_base_of_v<T, U>>>
  SmartPointer(SmartPointer<U> const& other)
  {
    if (pointer = other.pointer, refcount = other.refcount)  //友元模板的設(shè)置才能訪問other的私有變量
    {
        refcount->increment();
    }
  }
  //...
}

如果像讓不同的每個myLog的實例類都能互相訪問私有數(shù)據(jù),則可以這么做:

template<typename T> 
class myLog
{
    //...
    template<typename>
    friend class myLog;
    //...
}

這樣,myLog家族類之間就沒有秘密了。仔細琢磨,這挺神奇的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容