重载运算符<<- C++ [英] Overloading operator &lt;&lt; - C++

查看:98
本文介绍了重载运算符<<- C++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我有一个容器类,它使用 vector<std::string>内部.我已经为这个包装类提供了一个方法 AddChar(std::string) ,它对内部向量执行 push_back() .在我的代码中,我必须在某个时候向容器添加多个项目.为此,我必须使用

I have a container class which uses vector<std::string> internally. I have provided a method AddChar(std::string) to this wrapper class which does a push_back() to the internal vector. In my code, I have to add multiple items to the container some time. For that I have to use

container.AddChar("First");
container.AddChar("Second");

这使得代码更大.所以为了让它更容易,我计划重载运算符<<.这样我就可以写

This makes the code larger. So to make it more easier, I plan to overload operator <<. So that I can write

container << "First" << "Second"

两个项目将被添加到基础向量中.

and two items will get added to underlying vector.

这是我使用的代码

class ExtendedVector
{
private:
    vector<string> container;

public:
    friend ExtendedVector& operator<<(ExtendedVector& cont,const std::string str){
        cont.AddChar(str);
        return cont;
    }

    void AddChar(const std::string str)
    {
        container.push_back(str);
    }

    string ToString()
    {
        string output;
        vector<string>::iterator it = container.begin();
        while(it != container.end())
        {
            output += *it;
            ++it;
        }
        return output;
    }
};

它按预期工作.

问题

  1. 运算符重载是否正确编写?
  2. 在这种情况下重载运算符是一个好习惯吗?
  3. 此代码是否会出现任何性能问题或任何其他问题?

有什么想法吗?

编辑

在听到精彩的评论后,我决定不超载<<因为在这里没有意义.我删除了运算符重载代码,这是最终代码.

After hearing the excellent comments, I decided not to overload << as it doesn't make sense here. I removed the operator overload code and here is the final code.

class ExtendedVector
{
private:
    vector<string> container;

public:

    ExtendedVector& AddChar(const std::string str)
    {
        container.push_back(str);
        return *this;
    }

         .. other methods
}

这允许我添加

container.AddChar("First").AddChar("Second")

在 C# 中,我可以使用 params 关键字更轻松地完成此操作.代码会像

In C#, I can do this more easily by using the params keyword. Code will be like

void AddChar(params string[] str)
{
    foreach(string s in str)
       // add to the underlying collection
}

我知道在 C++ 中,我们可以使用 ... 来指定参数的可变长度.但是 AFAIK,它不是类型安全的.那么这样做是推荐的做法吗?这样我就可以写

I know in C++, we can use ... to specify variable langth of parameters. But AFAIK, it is not type safe. So is it a recommended practice to do so? So that I can write

container.AddChar("First","Second")

感谢您的回复.

推荐答案

运算符重载是否正确编写?

Is operator overload written correctly?

确实如此,但可以做得更好.就像其他人提到的那样,您的函数可以完全由现有的公共函数定义.为什么不让它只使用那些?现在,它是一个朋友,这意味着它属于实现细节.如果你把 operator<<<;作为班级的成员.但是,让您的运营商<<非会员非好友功能.

It is, but one can do better. Like someone else mentioned, your function can be defined entirely out of existing, public functions. Why not make it use only those? Right now, it is a friend, which means it belongs to the implementation details. The same is true if you put operator<< as a member into your class. However, make your operator<< a non-member, non-friend function.

class ExtendedVector {
    ...
};

// note, now it is *entirely decoupled* from any private members!
ExtendedVector& operator<<(ExtendedVector& cont, const std::string& str){
    cont.AddChar(str);
    return cont;
}

如果你改变你的班级,你将无法确定你的运营商<<仍然会工作.但是,如果您的运营商<<完全仅依赖于公共函数,那么您可以确定它仅在对类的实现细节进行更改后才能工作.耶!

If you change your class, you will not be sure that that your operator<< will still work. But if your operator<< entirely depends only on public functions, then you can be sure that it will work after changes were made to implementation details of your class only. Yay!

在这种情况下重载运算符是一个好习惯吗?

Is it a good practice to overload operators in situations like this?

正如另一个人再次所说,这是有争议的.在许多情况下,运算符重载乍一看看起来很整洁",但明年看起来会很糟糕,因为在给予某些符号特殊爱时,您不再知道自己在想什么.在 operator<<的情况下,我认为这是可以使用的.它用作流的插入运算符是众所周知的.我知道 Qt 和 KDE 应用程序在诸如

As another guy said again, this is arguable. In many situations, operator overloading will look "neat" at first sight, but will look like hell next year, because you have no clue anymore what you had in mind when giving some symbols special love. In the case of operator<<, i think this is an OK use. Its use as an insertion operator for streams is well known. And i know of Qt and KDE applications that use it extensively in cases like

QStringList items; 
items << "item1" << "item2";

一个类似的例子是 boost.format,它也重用了 operator% 来为它的字符串中的占位符传递参数:

A similar case is boost.format which also reuses operator% for passing arguments for placeholders in its string:

format("hello %1%, i'm %2% y'old") % "benny" % 21

在那里使用它当然也有争议.但是它对 printf 格式指定的使用是众所周知的,因此它在那里也可以使用,恕我直言.但一如既往,风格也是主观的,所以请持保留态度:)

It's of course also arguable to use it there. But its use for printf format specifies are well known and so its use is OK there too, imho. But as always, style is also subjective so take it with a grain of salt :)

如何以类型安全的方式接受可变长度参数?

How can i accept variable length arguments in a typesafe way?

好吧,如果您正在寻找同构参数,有一种接受向量的方法:

Well, there is the way of accepting a vector if you are looking for homogeneous arguments:

void AddChars(std::vector<std::string> const& v) {
    std::vector<std::string>::const_iterator cit =
        v.begin();
    for(;cit != v.begin(); ++cit) {
        AddChar(*cit);
    }
}

虽然通过它并不是很舒服.您必须手动构建您的向量,然后通过...我看到您已经对 vararg 样式函数有正确的感觉.不应将它们用于此类代码,并且仅在与 C 代码或调试函数接口时才使用.处理这种情况的另一种方法是应用预处理器编程.这是一个高级主题,并且非常棘手.这个想法是自动生成达到某个上限的重载,大致如下:

It's not really confortable to pass it though. You have to construct your vector manually and then pass... I see you already have the right feeling about the vararg style functions. One should not use them for this kind of code and only when interfacing with C code or debugging functions if at all. Another way to handle this case is to apply preprocessor programming. This is an advanced topic and is quite hacky. The idea is to automatically generate overloads up to some upper limit roughly like this:

#define GEN_OVERLOAD(X) \
void AddChars(GEN_ARGS(X, std::string arg)) { \
    /* now access arg0 ... arg(X-1) */ \
    /* AddChar(arg0); ... AddChar(arg(N-1)); */ \
    GEN_PRINT_ARG1(X, AddChar, arg) \
}

/* call macro with 0, 1, ..., 9 as argument
GEN_PRINT(10, GEN_OVERLOAD)

那是伪代码.您可以在此处.

That is pseudo code. You can have a look at the boost preprocessor library here.

下一个 C++ 版本将提供更好的可能性.可以使用初始化列表:

Next C++ version will offer far better possibilities. Initializer lists can be used:

void AddChars(initializer_list<std::string> ilist) {
    // range based for loop
    for(std::string const& s : ilist) {
        AddChar(s);
    }
}

...
AddChars({"hello", "you", "this is fun"});

在下一个 C++ 中也可以使用 可变参数模板.GCC4.4 将支持它们.GCC 4.3 已经部分支持它们.

It's also possible in next C++ to support arbitrary many (mixed-type) arguments using variadic templates. GCC4.4 will have support for them. GCC 4.3 already partially supports them.

这篇关于重载运算符<<- C++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆