簡體   English   中英

我該如何解決該成員函數問題重載的地址?

[英]How can I resolve this address of overloaded member function issue?

[ 編輯 -我很早就忘記了這里,直到我得到2500個視圖的“顯着問題”。 由於人們正在查看-在接受的答案中有關於重載的有用信息,但特別是檢查std::endl情況甚至比我當時意識到的還要糟糕,這肯定是錯誤的事情。

基本上, std::endl的作用是將\\n輸出到流中,然后使用std::flush 這與平台無關,包括Windows,其行尾實際上是“ \\ r \\ n”。 endl操縱器並沒有抽象出WRT行末端的平台差異,C ++處理C的方式與之相同-稍后將\\n轉換為“ \\ r \\ n”(對於文本模式,不是二進制)。 我以為C ++會做一些不同的事情,這個假設是如此強烈,以至於20年來我從未質疑過它,但是我錯了。

我不記得詳細信息,但是仍然可以定義自己的流,並提供流輸入的任何字符的替代輸出(和翻譯)。 您的自定義流代碼看到生成的輸出字符之前 ,所有操縱器都應按預期工作。 因此,要提供特殊的行尾行為,請注意其中的\\n (仍在文本文件行尾翻譯之前)。 ]

我知道這很棘手,但是最近我需要實現一個流類,該流類的行為基本上像是標准流,但是可以檢測到std :: endl操縱器,並在特殊情況下可以檢測其行為。 我對特定方法實現的首次嘗試是...

mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
  if (p == &std::endl)
  {
    //  Handle special case
  }
  else
  {
    m_Underlying_Stream << p;
  }

  return *this;
}

麻煩的是,編譯器不知道我指的是std::endl重載。 我如下解決了...

mystream& mystream::operator<< (std::basic_ostream<char>& (*p) (std::basic_ostream<char>&))
{
  typedef std::basic_ostream<char>& (*ENDL_T) (std::basic_ostream<char>&);

  const ENDL_T l_ENDL (&std::endl);

  if (p == l_ENDL)
  {
    //  Handle special case
  }
  else
  {
    m_Underlying_Stream << p;
  }

  return *this;
}

也就是說,編譯器可以在初始化的上下文中解決重載(並且也可以進行賦值,正如另一個實驗證明的那樣),但對於operator==不能。

有問題的編譯器是MinGW GCC 4.4.0,但我認為這可能不是編譯器問題。

我環顧四周,發現了這個問題...

如何獲取重載成員函數的地址?

如果我的代碼有一個const問題,我不知道丟失的const需要去哪里。 我看不到其他明顯的類型問題。

我對WRT重載或隱式轉換的步數問題有一些模糊的想法,但是沒有具體的想法。 所以-任何人都可以清楚地說明我的第一個示例有什么問題,為什么第二個版本可以解決它,以及在使用函數地址時我如何可以安全地指出我的意思是哪個重載。

順便說一句-我猜有些人可能不喜歡我直接測試std::endl的地址,並且會指出這很脆弱-例如某人可以擁有自己的操縱器,調用std::endl ,而我不會點。 總的來說,這是對的,但是在這種特殊情況下,hack可以節省很多時間,而無關緊要。

僅在有限的上下文集合中允許使用不帶參數的重載函數名稱(或行為類似於一組重載函數的函數模板的名稱)(例如在“ address of”表達式中)可用於唯一確定所需的特定過載。

這是在標准(ISO / IEC 14882:2003)[over.over]的13.4中指定的。 包括用於對象或引用或顯式轉換的初始化器。 這給您許多選擇。

例如顯式轉換:

typedef std::ostream& (*ManipPtr)(std::ostream&);

mystream& mystream::operator<<(ManipPtr p)
{
    if (p == static_cast<ManipPtr>(&std::endl))
    {
        // ...

直接初始化指針:

typedef std::ostream& (*ManipPtr)(std::ostream&);

mystream& mystream::operator<<(ManipPtr p)
{
    const ManipPtr pEndl = &std::endl;

    if (p == pEndl)
    {
        // ...

以下作品:

#include <iostream>

struct mystream {
    typedef std::basic_ostream<char>& (*ENDL_T) (std::basic_ostream<char>&);
    mystream& operator<< (ENDL_T p)
    {
        if (p == (ENDL_T)std::endl)
        {
            std::cout << "special case\n";
        }
        else
        {
            std::cout << "usual case\n";
        }
        return *this;
    }
};

int main()
{
    mystream ms;
    ms << std::endl; // prints "special case"
    ms << std::flush; // prints "usual case"
}

它無法區分重載的原因是因為您正在解析函數的地址,而不是調用它。 當您將其插入流中時,編譯器就會知道調用endl(ostream&)重載。 除此之外,您是一個人。

為什么不只測試'\\ n'呢?

暫無
暫無

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

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