简体   繁体   English

const struct object 访问成员函数(以及运算符重载问题)

[英]const struct object access member functions (and an operator overloading question)

I tried to overload the << operator for my custom struct , but encountered error C2662 , code as follows:我试图为我的自定义struct重载<<运算符,但遇到error C2662 ,代码如下:

struct HP{
    int max_hp;
    int hp;
    HP(int max_hp){
        this->max_hp=max_hp;
        this->hp=max_hp;
    }
    // this const declarative doesn't support const HP& obj argument
    const string repr(){
        stringstream hp_stats;
        hp_stats << this->hp << "/" << this->max_hp; 
        return hp_stats.str();
    }
    // This is fine with const HP& obj argument
    const string repr(){
        stringstream hp_stats;
        hp_stats << this->hp << "/" << this->max_hp; 
        return hp_stats.str();
    } 
};

// would cause error C2662
ostream& operator<<(ostream& out, const HP& obj){
    out<<obj.repr();
    return out;
}

I've found that this is because the implicitly access of this pointer, and const attempts to convert *this into const *this and thus fails.我发现这是因为this指针的隐式访问,并且const尝试将*this转换为const *this并因此失败。 But as I changed from const string repr() to string repr() const , it magically worked and compiled successfully.但是当我从const string repr()更改为string repr() const时,它神奇地工作并成功编译。

  1. What's the difference between a const T func(){} and T func() const , which makes a const struct object invoking feasible? const T func(){}T func() const有什么区别,这使得 const struct object 调用可行?

  2. I read it on cppreference.com, but still unsure why << overloading has to be declared outside a class scope.我在 cppreference.com 上阅读了它,但仍然不确定为什么必须在 class scope 之外声明 << 重载。

  3. Suppose I have repr() member function for struct HP , struct Shield , etc. I tried to make the << overloading a template function, but it turns that I am overloading << at global scope.假设我有repr()成员 function 用于struct HPstruct Shield等。我试图使 << 重载模板 function,但事实证明我正在重载 << 在全局 Z351A1FD140BEABEF8 Can I specify the T I am about to apply, OR apply the overloading across several classes with same member function, WITHOUT classes defined under one base class?我可以指定我将要应用的T ,或者在具有相同成员 function 的多个类中应用重载,而没有在一个基础 class 下定义类吗?

// complier thinks such overloading is global on <<
template <typename T>
ostream& operator<<(ostream& out, const T& obj){
    out<<obj.repr();
    return out;
}
  1. const T func() {} means that the return type is const T and the function might mutate the object. const T func() {}表示返回类型是const T ,并且 function 可能会改变 object。 Whereas, T func() const {} means that the return type is non-const but the object is unaltered ( const ).T func() const {}表示返回类型是非常量,但 object 未更改( const )。 You can also have both or neither const .您也可以同时拥有或不拥有const

  2. It doesn't have to be declared outside the class, it can be declared inside as a friend (non-member) function.它不必在 class 之外声明,它可以在内部声明为friend (非成员)function。 That works here as well.这也适用于这里。 However, for a member function: since operator<<() 's first parameter is ostream& , you could only declare it in ostream and not HP , which won't work.但是,对于成员 function:由于operator<<()的第一个参数是ostream& ,您只能在ostream而不是HP中声明它,这将不起作用。 Remember, member operators are like *this as the first argument of non-member operators.请记住,成员运算符就像*this作为非成员运算符的第一个参数。

  3. Yes, you can do this.是的,你可以这样做。 The easiest is to delegate to a common print function;最简单的就是委托给一个共同的印刷品 function; the more elegant way is to use std::enable_if , eg:更优雅的方法是使用std::enable_if ,例如:

template <typename T>
std::enable_if_v<std::is_same_v<T, HP> || std::is_same_v<t, Shield>, ostream&>
operator<<(ostream& out, const T& obj)
{
    out<<obj.repr();
    return out;
}

You can also write the conditions as a template and then re-use it:您还可以将条件编写为模板,然后重新使用它:

template<typename T>
using is_printable_v = std::is_same_v<T, HP> || std::is_same_v<T, Shield>;

template <typename T>
std::enable_if_v<is_printable_v<T>>, ostream&>
operator<<(ostream& out, const T& obj) { ... }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM