2010-02-04 60 views
3

嗯,我想知道爲什麼endd似乎並沒有執行(雖然它不會在編譯時產生任何錯誤)。C++ Manipulator not being

struct dxfDato 
{ 
    dxfDato(int c, string v = 0, int t = 0) { codigo = c; valor = v; tipo = t; } 
    dxfDato() { } 

    int tipo; 
    int codigo; 
    string valor; 
}; 
class dxfItem 
{ 
private: 
    std::ostringstream ss; 
    typedef std::ostream& (*manip)(std::ostream&); 

public: 
    int clase; 
    string valor; 
    vector<dxfDato> datos; 
    vector<dxfItem> hijos; 

    template <typename T> 
    dxfItem& operator<<(const T& x) 
    { 
     ss << x; 
     return *this; 
    } 
    dxfItem& operator<<(manip x) // to store std manipulators 
    { 
     ss << x; 
     return *this; 
    } 
    static dxfItem& endd(dxfItem& i) // specific manipulator 'endd' 
    { 
     dxfDato dd; 
     dd.valor = i.ss.str(); 
     i.datos.push_back(dd); 

     std::cout << "endd found!" << endl; 
     return i; 
    } 
}; 

/* blah blah blah */ 

dxfItem header; 

header 
    << 9 << endl << "$ACADVER" << endl << 1 << endl << "AC1500" << endl 
    << dxfItem::endd // this apparently doesn't execute anything 
    << "other data" << endl 
; 

這是我在嘗試開發某些東西時發現的最後一個問題。最後一件事暴露在這裏:C++ Operator overloading example

謝謝大家!

回答

4

你定義的類型manip是一個函數,通過引用,採用一個std::ostream和通過引用返回std::ostream,但您已經定義endd採取dxfItem並返回dxfItemdxfItem不來自std::ostream

由於此類型不匹配,編譯器正在生成對operator<<模板的調用,而不是manip過載。

此外,您 manip超載需要實際調用傳遞給它的機械手功能:

dxfItem& operator<<(manip x) 
{ 
    x(ss); 
    return *this; 
} 

+0

絕對如此。無論如何,談論你的答案的第二部分:爲什麼使用'ss << std :: x;'仍然不會調用操縱器'std :: x(ss);'? – huff 2010-02-04 15:31:16

+0

@huff,其實你是對的。如果你正在爲自己的類型創建一個操縱器(比如dxfItem),你需要使用函數調用語法,但是由於std :: ostringstream有自己的操作符<<操作符的重載,所以你應該可以使用操作符。 – 2010-02-04 15:37:29

0

我認爲這個問題我是這一行

<< dxfItem::endd // this apparently doesn't execute anything 

應該像在C++語言中的

<< dxfItem::endd(Whatever argument goes in here) 
-1

功能(以及在C)被稱爲(「執行」 )由一個函數調用運算符()(它也可以爲函數提供參數)。我沒有看到代碼中的任何函數調用運算符直接或間接應用於endd函數。這就是它從未被執行的原因。

+2

你知道操縱的C++流圖書館? – 2010-02-04 15:04:01

+0

考慮到答案,它似乎並不如此。雖然我猜我不知道他們要麼! :D – huff 2010-02-04 15:07:07

+0

@Alexander Poluektov:嗯?是的,我知道。你是?顯然你很少有想法,關於這樣一個事實,即像C++中的'ends'這樣的操作符通過被* << *'過載的* *函數調用操作符*調用來操作庫操作。 – AnT 2010-02-04 15:35:12

1

您嘗試執行時使用的語法endd讓我覺得您想將其用作endlendl是一種特殊的結構,稱爲機械手。你可以構建你自己的操縱者,但這不是一個膽小的人(或初學者)的話題。

(無論如何,如果你仍然想使endd操縱器,谷歌的「C++流處理器教程」 ......)

+0

不,我不想用'endl',我也不想重新定義'endl'。我希望兩個操縱器共存。我仍在研究:D。我會更正標題以更準確。 – huff 2010-02-04 15:09:57

+0

我的措辭讓我不清楚。我明白你想讓兩者共存,我只是指着你一個像'endl'這樣的結構的正確名稱。 – 2010-02-04 15:13:27

+0

好的。我仍然無法找到錯誤。我不認爲這與存儲'std'操縱器(這是我的隨機猜測)的方法有關...:P – huff 2010-02-04 15:18:14

1

要被稱爲機械手,你的函數的類型應該是std::ostream& (*)(std::ostream& strm)

請注意,在當前的C++中不允許使用參數定義您自己的操縱器。

1

同意並阿德里安Plisson意見,以瞭解更多有關機械手,我可以告訴你如何做到什麼,我想你想:

typedef dxfItem& (*noArgdxfManip)(dxfItem &); // here is the type for your manipulator 

dxfItem & operator << (noArgdxfManip manip) 
{ 
    return manip(*this); 
} 

如果你能理解這個代碼,就可以理解了操縱的伎倆工作。通常情況下,如果流看到一個傳遞給它的函數指針,它只是試圖打印其內容。但是對函數指針有一個重載,這些函數指針對流和返回流進行操作,而不是在流上打印指針調用指向的函數。在這裏你可以爲你的dxfItem類做同樣的事情。

免責聲明 我沒有嘗試編譯它,因此它可能包含一些語法錯誤。

1

如前所述,標準流使用重載運算符,該運算符采用操縱器類型的函數指針,然後調用該操縱器來實現該行爲。

您提供的typedef和重載運算符< <應該允許您使用標準操縱符,因爲預期的函數接受並返回一個ostream &。

你沒有聲明重載運算符< <,需要一個函數指針,接受並返回dxfItem &的功能,所以它會使用默認的操作< <這應該只是存儲/打印功能的地址,而比執行操縱器。

你需要建立一個typedef爲您的手:

typedef dxfItem& (*endd_manip)(dxfItem&); 

然後您可以創建一個重載的操作< <它:

dxfItem& operator<<(endd_manip x) 
{ 
    // Call the manipulator on the stream. 
    x(*this); 

    return *this; 
}