首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >模板Polynom类的重载operator[]

模板Polynom类的重载operator[]
EN

Stack Overflow用户
提问于 2011-11-09 09:20:04
回答 5查看 1.6K关注 0票数 3

我正在编写一个模板Polynom<T>类,其中T是其系数的数值类型。

多边形的系数存储在std::vector<T> coefficients中,其中coefficients[i]对应于实多边形中的x^i。(因此x的幂在增加)。

保证coefficients向量始终包含至少一个元素。-对于零倍数,它是T()

我想使operator[]过载以执行以下操作:

  1. 传递给operator[]的索引对应于X的幂,我们希望修改/读取它的系数。
  2. 如果用户只想读取系数,它应该抛出负索引,对存储范围内的索引返回coefficients.at(i),对于所有其他索引,合理地返回0,而不是抛出。H 217H 118如果用户想要修改E 119修改E 220系数,它应该抛出负性索引,但允许用户自由修改所有其他索引,即使指定的索引大于或等于<>D21代码。因此,我们想以某种方式调整向量的大小。

我遇到的主要问题如下:

1.

如何区分读大小写和写大小写?有一个人没有给我解释,而是说写了两个版本:

代码语言:javascript
复制
const T& operator[] (int index) const;
T& operator[] (int index);

还不够。但是,我认为编译器会更喜欢read情况下的const版本,不是吗?

2.

我想确保没有尾随零存储在coefficients向量中。因此,我必须事先知道,“之前”我返回一个可变的T&,我的系数,用户想要分配的值。我知道operator[]没有收到第二个论点。

显然,如果这个值不是零(不是T()),那么我必须调整向量的大小,并将适当的系数设置为传递的值。

但是我不能提前完成(在从T&返回operator[]之前),因为如果要赋值的值是T(),那么,只要我提前调整系数向量的大小,它最终就会有大量的尾随“零”。

当然,我可以在类的所有其他函数中检查尾随零,并在这种情况下删除它们。在我看来,这似乎是一个非常奇怪的决定,我希望每个函数都能开始工作,假设向量的末尾没有零,如果它的大小大于1时。

你能给我建议一下这个问题的具体解决办法吗?我听说了一些关于使用重载的T&隐式可转换为operator=的内部类,但我缺乏细节。

非常感谢您提前!

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-11-09 09:26:29

您可以尝试一个选项(我还没有对此进行测试):

代码语言:javascript
复制
template<typename T>
class MyRef{
private:
   int index;
   Polynom<T>*p;
public:
    MyRef(int index, Polynom<T>*p) : index(index), p(p) { }

    MyRef<T>& operator=(T const&t); //and define these appropriately
    T operator T() const;         
};

并界定:

代码语言:javascript
复制
    MyRef<T> operator[](int index){
        return MyRef<T>(index, this);
    }

这样,当您为“引用”赋值时,它应该能够访问多项式中所有需要的数据,并采取适当的操作。

我对您的实现还不太熟悉,因此我将给出一个非常简单的动态数组的示例,其工作方式如下:

您可以不用担心地从任何0;

  • when中读取
  • ;当您在当前分配的数组结束后将其写入元素时,应该将以前未写入的元素读取掉,重新分配它,并将新分配的元素初始化为0.

代码语言:javascript
复制
#include <cstdlib>
#include <iostream>
using namespace std;

template<typename T>
class my_array{
private:
    T* _data;
    int _size;

    class my_ref{

        private:
            int index;
            T*& obj;
            int&size;
        public:
            my_ref(T*& obj, int&size, int index)
                : index(index), obj(obj), size(size){}

            my_ref& operator=(T const& t){

                if (index>=size){    
                    obj = (T*)realloc(obj, sizeof(T)*(index+1) );
                    while (size<=index)
                        obj[size++]=0;
                }
                obj[index] = t;

                return *this;
            }

            //edit:this one should allow writing, say, v[1]=v[2]=v[3]=4;
            my_ref& operator=(const my_ref&r){              
                operator=( (T) r);
                return *this;
            }

            operator T() const{
                return (index>=size)?0:obj[index];
            }

    };

public:
    my_array() : _data(NULL), _size(0) {}

    my_ref operator[](int index){
        return my_ref(_data,_size,index);
    }

    int size() const{ return _size; }

};

int main(){

    my_array<int> v;

    v[0] = 42;
    v[1] = 51;
    v[5] = 5; v[5]=6;
    v[30] = 18;

    v[2] = v[1]+v[5];
    v[4] = v[8]+v[1048576]+v[5]+1000;

    cout << "allocated elements: " <<  v.size() << endl;
    for (int i=0;i<31;i++)
        cout << v[i] << " " << endl;

    return 0;
}

这是一个非常简单的例子,目前的形式并不十分有效,但它应该能证明这一点。

最终,您可能希望重载operator&,以允许像*(&v[0] + 5) = 42;这样的东西正常工作。对于这个例子,您可以让operator&给出一个my_pointer,它定义了operator+来对其index字段执行算术,并返回一个新的my_pointer。最后,您可以重载operator*()以返回到my_ref

票数 4
EN

Stack Overflow用户

发布于 2011-11-09 09:47:29

解决方案是一个代理类(未经测试的代码如下所示):

代码语言:javascript
复制
template<typename T> class Polynom
{
public:
   class IndexProxy;
   friend class IndexProxy;
   IndexProxy operator[](int);
   T operator[](int) const;
   // ...
private:
   std::vector<T> coefficients;
};

template<typename T> class Polynom<T>::IndexProxy
{
public:
  friend class Polynom<T>;
  // contrary to convention this assignment does not return an lvalue,
  // in order to be able to avoid extending the vector on assignment of 0.0
  T operator=(T const& t)
  {
    if (theIndex >= thePolynom.coefficients.size())
      thePolynom.coefficients.resize(theIndex+1);
    thePolynom.coefficients[theIndex] = t;
    // the assignment might have made the polynom shorter
    // by assigning 0 to the top-most coefficient
    while (thePolynom.coefficients.back() == T())
      thePolynom.coefficients.pop_back();
    return t;
  }
  operator T() const
  {
    if (theIndex >= thePolynom.coefficients.size())
      return 0;
    return thePolynom.coefficients[theIndex];
  }
private:
  IndexProxy(Polynom<T>& p, int i): thePolynom(p), theIndex(i) {}
  Polynom<T>& thePolynom;
  int theIndex;
}

template<typename T>
  Polynom<T>::IndexProxy operator[](int i)
  {
    if (i < 0) throw whatever;
    return IndexProxy(*this, i);
  }

template<typename T>
  T operator[](int i)
{
  if (i<0) throw whatever;
  if (i >= coefficients.size()) return T();
  return coefficients[i];
}

显然,上面的代码没有被优化(特别是赋值操作符有明显的优化空间)。

票数 2
EN

Stack Overflow用户

发布于 2011-11-09 09:27:07

不能区分操作符重载的读和写。最好的方法是区分const设置中的用法和非const设置,这就是您的代码片段所做的。所以:

代码语言:javascript
复制
Polynomial &poly = ...;

poly[i] = 10;  // Calls non-const version
int x = poly[i];  // Calls non-const version

const Polynomial &poly = ...;

poly[i] = 10;   // Compiler error!
int x = poly[i]  // Calls const version

因此,听起来这两个问题的答案都是有单独的setget函数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8062731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档