【问题标题】:Read Only Class Variables (C++) and Operator Overloading只读类变量 (C++) 和运算符重载
【发布时间】:2017-07-03 23:01:44
【问题描述】:

取以下代码:

#include <string>
#include <iostream>

template <class T, class U>
class readonly
{
  friend U;
  private:
    T data;
    T operator=(const T& arg) {data = arg; return data;}
    T operator+=(const T& arg) {data = data + arg; return data;}
    T operator-=(const T& arg) {data = data - arg; return data;}
    T operator*=(const T& arg) {data = data * arg; return data;}
    T operator/=(const T& arg) {data = data / arg; return data;}
  public:
    operator const T&() const {return data;}
};

class myClass
{
  private:
    typedef readonly<int, myClass> RO_int;
    typedef readonly<std::string, myClass> RO_string;

  public:
    RO_int x;
    RO_string y;

    void f()
    {
      x = 55;
      y = "Howdy";
      std::cout << x << "\n\n";  // compiles fine
      std::cout << y << "\n\n";  // compile error
    }
};

我使用这些模板类来确保某些公共变量xy 在类之外是“只读”的,但可以在类本身内进行修改。除了最后一行我试图显示字符串类型的变量 y 之外,这段代码中的所有内容都可以正常编译。我不明白为什么我可以显示x 但不能显示y。如果我需要重载&lt;&lt; 运算符,为什么我必须为std::string 而不是int

【问题讨论】:

  • 这只是一个包含在 main.cpp 中的头文件。我在 main.cpp 中所做的只是创建一个 myClass 类型的对象,然后调用函数 f()。对不起,我应该说得更清楚。
  • int 的输出是 0,所以我不认为它使用正确的重载来显示x。可能您需要重载 &lt;&lt; 以使其适用于任何类型。
  • 对于一些简单的事情来说似乎有很多机制:private: int x_; public: int x() const { return x_; }
  • @PeteBecker,虽然我同意你的观点,但我只是想避免使用 () 符号,因为它会迫使我重写很多代码。我也想避免它使我访问这些变量的数百个地方更短。

标签: c++ templates operator-keyword


【解决方案1】:

首先,但不是您的问题,您的运营商应该返回readonly&amp;T&amp; 而不是T。不要那样打破惯例。

现在是一个实际的答案。

因为string使用的operator&lt;&lt;是模板,模板函数在模式匹配时不考虑转换。采用int&lt;&lt; 不是模板,因此它会考虑转换。

我们可以通过创建一个不转换的operator&lt;&lt; 来解决这个问题:

简单添加

friend std::ostream& operator<<(std::ostream& os, readonly const& self)
{
  return os<<self.data;
}

到您的readonly 类型,一切都会正常。这将通过 ADL 找到。

我们可以通过模板获取第一个参数并检查&lt;&lt; 是否有效以及第一个参数是否派生自std::ostream 或第二个参数的类似方法,从而使 SFINAE 等更有趣。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-19
    • 2011-11-29
    • 1970-01-01
    • 2015-07-17
    • 2010-10-19
    • 2020-07-22
    相关资源
    最近更新 更多