2010-02-04 57 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; 
}