考虑以下简单的类。
#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];
}
}
};
它的行为应类似于动态数组。我重载了()运算符。我的想法是,对于赋值(lvalue),将调用()的较高版本,对于“只读”操作(rvalue),将使用()的较低版本。示例代码应该更清楚地解释我的意思:
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;
}
因此,我通过()运算符访问myvar
的内容。应该可以只为 any 元素分配一个值,但是不可能查询以前从未设置过的元素的值。我以为可以使用()的不同版本,其中一个const
就足够了,但是显然,编译器始终使用运算符的较高版本,而从未使用较低版本。我该如何解决这个问题?
我阅读了有关代理对象(例如here)的信息,但是我认为这种实现在我的情况下将无法正常工作,因为我正在使用数组。所以 a)没有代理人是否有可能,如果没有 b)在我的情况下,代理应该是什么样子?
答案 0 :(得分:0)
所以这是我终于想出的解决方案:
#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;
}
终端上的输出如下:
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