簡體   English   中英

將前向聲明的 class 的成員函數聲明為朋友

[英]Declare a member-function of a forward-declared class as friend

是否可以將前向聲明的 class 的成員 function 聲明為朋友? 我正在嘗試執行以下操作:

class BigComplicatedClass;

class Storage {
   int data_;
public:
   int data() { return data_; }
   // OK, but provides too broad access:
   friend class BigComplicatedClass;
   // ERROR "invalid use of incomplete type":
   friend void BigComplicatedClass::ModifyStorage(); 
};

所以目標是 (i) 將友元聲明限制為單個方法,以及 (ii) 不包括復雜的 class 的定義以減少編譯時間。

一種方法可能是添加一個 class 作為中介:

// In Storage.h:
class BigComplicatedClass_Helper;
class Storage {
    // (...)
    friend class BigComplicatedClass_Helper;
};

// In BigComplicatedClass.h:
class BigComplicatedClass_Helper {
     static int &AccessData(Storage &storage) { return storage.data_; }
     friend void BigComplicatedClass::ModifyStorage();
};

但是,這似乎有點笨拙......所以我認為必須有更好的解決方案!

正如@Ben 所說,這是不可能的,但您可以通過"passkey"僅向該成員 function 授予特定訪問權限。 它的工作方式有點像中間助手 class,但更清楚:

// Storage.h
// forward declare the passkey
class StorageDataKey;

class Storage {
   int data_;
public:
   int data() { return data_; }
   // only functions that can pass the key to this function have access
   // and get the data as a reference
   int& data(StorageDataKey const&){ return data_; }
};

// BigComplicatedClass.cpp
#include "BigComplicatedClass.h"
#include "Storage.h"

// define the passkey
class StorageDataKey{
  StorageDataKey(){} // default ctor private
  StorageDataKey(const StorageDataKey&){} // copy ctor private

  // grant access to one method
  friend void BigComplicatedClass::ModifyStorage();
};

void BigComplicatedClass::ModifyStorage(){
  int& data = storage_.data(StorageDataKey());
  // ...
}

不,您不能將單個成員函數聲明為朋友,直到它們被聲明。 您只能與整個 class 成為朋友。

它在這里可能相關也可能不相關,但提醒我們自己,除了 scope 的類和對象之外,還有一個功能可以自由漫游的狂野世界。

例如,我最近需要從基於他人代碼端口的全局異常處理程序中關閉(單例全局靜態)系統錯誤日志。 我的錯誤日志的正常包含文件與異常處理程序代碼沖突,因為出於我沒有調查的原因,兩者都想包含“windows.h”。 當這個問題和其他問題說服我時,我無法對 ErrorLog 類的成員函數進行前向聲明,我所做的是將必要的函數包裝到全局 scope function 中,如下所示:

void WriteUrgentMessageToErrorLog( const char * message )
{
  ErrorLog::LogSimpleMessage( message );
  ErrorLog::FlushAccumulatedMessagesToDisk();
}

有些人非常注重不惜一切代價維護其 class 結構的完整性......並且很少承認使用這些類的應用程序不可避免地構建在缺乏該結構的東西之上。 但它就在那里,並且被明智地使用,它有它的位置。

考慮到這個問題的年代久遠,我在這里沒有深入研究它的相關性。 我想分享的只是這樣一種觀點,有時像這樣的簡單包裝機制是一種更簡潔、更容易理解的替代方案,而不是更微妙和更聰明的東西。 微妙和聰明往往會在以后被需要添加但不完全理解的人改變。 在不知不覺中,你有一個錯誤......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM