简体   繁体   English

C ++ overload()运算符,左值和右值

[英]C++ overload () operator, lvalue and rvalue

Consider the following simple class. 考虑以下简单类。

#include <iostream>

using namespace std;

class test
{
public:
  int* myvar;
  int sz;

  test()
  {
    sz = 10;
    myvar = new int[10];
  }

  void dump()
  {
    for(int i = 0; i < sz; i++)
    {
      cout << myvar[i] << " ";
    }
    cout << endl;
  }

  int& operator()(int index)
  {
    if(index >= sz)
    {
      int* newvar = new int[index+1];

      for(int i = 0; i < sz; i++)
      {
        newvar[i] = myvar[i];
      }
      sz = index+1;
      delete myvar;
      myvar = newvar;
    }
    return myvar[index];
  }

  const int operator()(int index) const
  {
    if(index >= sz)
    {
      throw "index exceeds dimension";
    }
    else
    {
      return myvar[index];
    }
  }
};

It should behave like a dynamic array. 它应该像动态数组一样。 I overloaded the () operator. 我重载了()运算符。 My idea was, that for an assignment (lvalue), the upper version of the () will be called, and for a "read only" operation (rvalue) the lower version of () is used. 我的想法是,对于赋值(左值),将调用()的高级版本,对于“只读”操作(rvalue),使用较低版本的()。 The sample code should explain more clearly what I mean: 示例代码应该更清楚地解释我的意思:

int main()
{
  test x;

  // will give 10 times zero
  x.dump();

  // assign some values
  x(1) = 7;
  x(9) = 99;

  // will give
  // 0 7 0 0 0 0 0 0 0 99
  x.dump();

  // should give 7
  cout << x(1) << endl;

  // should give 99
  cout << x(9) << endl;

  // this will increase the size of myvar to 15 elements and assign a value
  x(15) = 15;

  // this should give
  // 0 7 0 0 0 0 0 0 0 99 0 0 0 0 0 15
  x.dump();

  // this should throw an exception because x(20) got never assigned a value!
  // but instead of calling the lower version of operator() it also calls the
  // upper, resulting in x being expanded now to 21 elements.
  cout << x(20) << endl;

  // will give 21 elements, instead of 16.
  x.dump();

  return 0;
}

So I access the contents of myvar via the () operator. 所以我通过()运算符访问myvar的内容。 It should be possible to assign a value just to any element, but it shall not be possible to query the value of an element that has never been set before. 应该可以为任何元素分配一个值,但是不可能查询之前从未设置过的元素的值。 I thought by using different versions of (), one of which being const should suffice, but apparently, the compiler is always using the upper version of my operator, and never the lower. 我想通过使用不同版本的(),其中一个是const应该足够,但显然,编译器总是使用我的运算符的上层版本,而不是更低版本。 How can I fix this problem? 我该如何解决这个问题?

I read about the proxy object, eg here , but I think this implementation will not work in my case because I am using an array. 我读到了代理对象,例如这里 ,但我认为这个实现在我的情况下不起作用,因为我使用的是数组。 So a) is it possible without the proxy, or if not b) how should the proxy look like in my case? 所以a)是否可能没有代理,或者如果不是b)在我的情况下代理应该怎么样?

So this is the solution I finally came up with (sort of): 所以这是我最终提出的解决方案(有点):

#include <iostream>

using namespace std;

template <class T> class myclass
{
private:
  unsigned numel;
  T* elem;

public:

  class proxy
  {
    private:

        T*& elem;
        unsigned& numel;
        const unsigned index;

        proxy(T*& elem, unsigned& numel, unsigned index) : elem(elem), numel(numel), index(index) { }

        // didn't really need those two
        // proxy(const proxy&) = default;
        // proxy(proxy&&) = default;

        friend class myclass;

    public:
        proxy& operator=(const T& value)
        {
          if(index >= numel)
          {
            cout << "assignment to an element outside the range!" << endl;
            cout << "old size: " << numel << endl;
            cout << "new size: " << index+1 << endl << endl;

            T* newelem = new T[index+1];
            for(unsigned i = 0; i <= index; i++)
            {
              if(i < this->numel)
              {
                newelem[i] = this->elem[i];
              }
              else
              {
                newelem[i] = 0;
              }
            }

            if(this->elem != nullptr)
            {
              delete this->elem;
            }
            this->elem = newelem;
            this->numel = index+1;
          }

          this->elem[index] = value;
          return *this;
        }

        proxy& operator=(const proxy &other)
        {
          *this = (const T&)other;
          return *this;
        }

        operator T&()
        {
          if(index >= numel)
          {
            cout << "cannot query the value of elements outside the range!" << endl;
            cout << "# of elements: " << numel << endl;
            cout << "index requested: " << index << endl << endl;

            throw out_of_range("");
          }
          return elem[index];
        }

        operator const T&() const
        {
          if(index >= numel)
          {
            throw out_of_range("");
          }
          return elem[index];
        }
    };

  myclass() : numel(0), elem(nullptr) {};

  myclass(unsigned count)
  {
    this->numel = count;
    this->elem = new T[count];
  }

  ~myclass()
  {
    if(this->elem != nullptr)
    {
      delete this->elem;
    }
  }


  friend ostream& operator<<(ostream& os, const myclass& mc)
  {
    os << endl;
    for(unsigned i = 0; i < mc.numel; i++)
    {
      os << mc.elem[i] << "  ";
      os << endl;
    }
    os << endl;
    return os;
  }

  proxy operator()(unsigned index)
  {
    return proxy(this->elem, this->numel, index);
  }

};


int main()
{
  myclass<double> my;

  my(1) = 77;
  my(0) = 200;
  my(8) = 12;

  cout << my;

  try
  {
    cout << my(0) << endl;
    cout << my(1) << endl;
    cout << my(8) << endl;
    cout << my(10) << endl;
  }
  catch(...)
  {
    cout << "error catched" << endl << endl;
  }

  my(10) = 10101;

  cout << my(10) << endl;

}

the output on the terminal looks like this: 终端上的输出如下所示:

assignment to an element outside the range!
old size: 0
new size: 2

assignment to an element outside the range!
old size: 2
new size: 9


200  
77  
0  
0  
0  
0  
0  
0  
12  

200
77
12
cannot query the value of elements outside the range!
# of elements: 9
index requested: 10

error catched

assignment to an element outside the range!
old size: 9
new size: 11

10101

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

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