扩展向量迭代器以访问包含的类/结构的数据成员

时间:2011-05-19 11:26:20

标签: c++ string vector iterator

所以,我有一个类根据附加到字符串中每个字符的元数据进行字符串操作。在内部,我用std::vector<CharacterType>代表这个,其中CharacterType包含所讨论的角色等。这个内部表示对我很有用,但是在操作结束时,类用户对字符串本身感兴趣。

为了做到这一点,我决定扩展std::vector<CharacterType>::iterator以包含一个返回字符而不是operator*()的{​​{1}}方法。这是代码,它适用于Windows 7上的Visual Studio 2008但是它是惯用的C ++吗?自90年代以来,我没有写过很多C ++,所以我很欣赏一些关于风格的反馈,或者我是否正在做一些危险和/或邪恶的事情。 (在下面的代码中,我创建了一个名为CharacterType的简化CharacterType结构 - 实际上结构要大得多。)

mytype

假设这是一个好的样式,使用C ++类型感知方法重载是否合适在#include <iostream> #include <vector> #include <string> struct mytype { char c; }; class myit : public std::vector<mytype>::iterator { public: inline myit(std::vector<mytype>::iterator const &c) : std::vector<mytype>::iterator(c) {} char operator*() { const mytype &p = std::vector<mytype>::iterator::operator*(); return p.c; } // Added these in a later edit, after thinking about a comment below typedef char value_type; typedef char *pointer; typedef char &reference; private: }; int main() { mytype test[] = { {'a'}, {'b'}, {'c'}, {'d'} }; std::vector<mytype> vec(&test[0], &test[4]); myit i(vec.begin()), e(vec.end()); std::string str(i, e); std::cout << str << std::endl; return 0; } 中有几个operator*()方法,以便我可以使用相同的迭代器类来获取另一个成员不同的类型?或者使用模板会更好吗?例如,一个元数据是角色的语言,我希望能够以完全相同的方式提取myit。想法?

此外,由于返回这些数据的方法不会影响对象的内部表示,为了保证const的正确性,我希望能够定义访问器std::vector<LanguageType>。这可能意味着我需要修改上面的内容才能使用const代替,但我还没有达到目的。

提前感谢你的风格批评!

5 个答案:

答案 0 :(得分:0)

首先,我希望能够在这么长的休息之后写出如此优秀的C ++,如果它应该发生在我身上的话!

说,从CharacterTypechar排除简单转化运算符的原因是什么?类似于:CharacterType::operator char();

当然,我们都知道运算符重载的问题(但在两种情况下不会改变)......

关于你问的其他事情,你不能基于返回类型重载,所以你不可能为不同的返回类型设置不同的operator(),如果这就是你的意思。

但正如你所提到的,你可以使用模板。

答案 1 :(得分:0)

你不应该派生std :: vector(也不是其他STL容器),因为它的析构函数不是虚拟的,你可以遇到没有调用vector的析构函数并且你得到内存泄漏的情况。

答案 2 :(得分:0)

我不相信你可以在同一个班级中“多次operator*()重载”;大概你想要基于返回类型消除歧义,但C ++不会这样做。

另外,直接从不相关的迭代器类型派生可能不是一个好主意。为了作为STL迭代器正确运行,迭代器类需要定义许多typedef等。如果你直接继承它们,那么你的任何一个都没有意义。有关更多信息,请参阅例如这篇文章在Custom Containers & Iterators for STL-Friendly Code

答案 3 :(得分:0)

您通过从operator*()返回CharacterType以外的类型来破坏多个迭代器契约。老实说 - 如果你迫切希望它们可以转换,只需给出operator char()字符。

答案 4 :(得分:0)

一些不同的人建议我研究转换运算符,我必须承认我完全忘了。基于转换运算符的解决方案相当简洁:

#include <iostream>
#include <vector>
#include <string>

struct mytype {
    char c;
    inline operator char () { return c; }
};

int
main()
{
    mytype test[] = { {'a'}, {'b'}, {'c'}, {'d'} };
    std::vector<mytype> vec(&test[0], &test[4]);
    std::string str(vec.begin(), vec.end());

    std::cout << str << std::endl;
    return 0;
}

...并且它不会让我担心违反STL迭代器合同等不祥的声音。另外,似乎(虽然我还没有尝试过)如果我希望能够轻松复制除字符串之外的其他内容(原始问题中的std::vector<LanguageType>想法),我可以通过添加来轻松扩展一个不同的强制转换操作符,而迭代器派生技术需要更多样板,因为C ++中没有返回类型多态,正如几个人指出的那样。

非常感谢您的回复,一旦我得到代表,我会全力支持您,以防您想知道我为什么还没有。