我正在编写一个模板Polynom<T>类,其中T是其系数的数值类型。
多边形的系数存储在std::vector<T> coefficients中,其中coefficients[i]对应于实多边形中的x^i。(因此x的幂在增加)。
保证coefficients向量始终包含至少一个元素。-对于零倍数,它是T()。
我想使operator[]过载以执行以下操作:
coefficients.at(i),对于所有其他索引,合理地返回0,而不是抛出。H 217H 118如果用户想要修改E 119修改E 220系数,它应该抛出负性索引,但允许用户自由修改所有其他索引,即使指定的索引大于或等于<>D21代码。因此,我们想以某种方式调整向量的大小。我遇到的主要问题如下:
1.
如何区分读大小写和写大小写?有一个人没有给我解释,而是说写了两个版本:
const T& operator[] (int index) const;
T& operator[] (int index);还不够。但是,我认为编译器会更喜欢read情况下的const版本,不是吗?
2.
我想确保没有尾随零存储在coefficients向量中。因此,我必须事先知道,“之前”我返回一个可变的T&,我的系数,用户想要分配的值。我知道operator[]没有收到第二个论点。
显然,如果这个值不是零(不是T()),那么我必须调整向量的大小,并将适当的系数设置为传递的值。
但是我不能提前完成(在从T&返回operator[]之前),因为如果要赋值的值是T(),那么,只要我提前调整系数向量的大小,它最终就会有大量的尾随“零”。
当然,我可以在类的所有其他函数中检查尾随零,并在这种情况下删除它们。在我看来,这似乎是一个非常奇怪的决定,我希望每个函数都能开始工作,假设向量的末尾没有零,如果它的大小大于1时。
你能给我建议一下这个问题的具体解决办法吗?我听说了一些关于使用重载的T&隐式可转换为operator=的内部类,但我缺乏细节。
非常感谢您提前!
发布于 2011-11-09 09:26:29
您可以尝试一个选项(我还没有对此进行测试):
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;
};并界定:
MyRef<T> operator[](int index){
return MyRef<T>(index, this);
}这样,当您为“引用”赋值时,它应该能够访问多项式中所有需要的数据,并采取适当的操作。
我对您的实现还不太熟悉,因此我将给出一个非常简单的动态数组的示例,其工作方式如下:
您可以不用担心地从任何0;
0.。
#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。
发布于 2011-11-09 09:47:29
解决方案是一个代理类(未经测试的代码如下所示):
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];
}显然,上面的代码没有被优化(特别是赋值操作符有明显的优化空间)。
发布于 2011-11-09 09:27:07
不能区分操作符重载的读和写。最好的方法是区分const设置中的用法和非const设置,这就是您的代码片段所做的。所以:
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因此,听起来这两个问题的答案都是有单独的set和get函数。
https://stackoverflow.com/questions/8062731
复制相似问题