我现在应该得到这个,但我还没有得到它。问题是operator =的参数可能是非const,但是它会破坏std :: vector :: push_back,因为它使项目为const,所以operator =必须接受一个const对象。好吧,我不确定我应该如何修改这个像这样工作的对象。
#include <vector>
#include <map>
#include <iostream>
using namespace std;
int font[] = {0, 31, 0, 31, 0, 31, 0, 31};
class Foo {
int size_;
std::map<int, int> chars_;
public:
Foo(int *font, int size);
unsigned int Size() const { return size_; }
void Add(int ch);
bool operator==(const Foo &rhv) const;
int &operator[](int i);
int const operator[](int i);
Foo operator=(const Foo &rhv);
};
Foo::Foo(int *font, int size) {
for(int i = 0; i < size; i++ ) {
chars_[size_++] = font[i];
}
}
bool Foo::operator==(const Foo &rhv) const {
if(Size() != rhv.Size()) return false;
/*for(int i = 0; i < Size(); i++ ) {
if ( chars_[i] != *rhv[i] )
return false;
}*/
return true;
}
int &Foo::operator[](int i) {
return chars_[i];
}
int const Foo::operator[](int i) {
return chars_[i];
}
Foo Foo::operator=(const Foo &rhv) {
if( this == &rhv ) return *this;
for(unsigned int i = 0; i < rhv.Size(); i++ ) {
//Add(*rhv[i]);
//chars_[size_++] = rhv[i];
}
return *this;
}
void Foo::Add(int ch) {
chars_[size_++] = ch;
}
int main()
{
vector<Foo> baz;
Foo bar = Foo(font, 8);
baz.push_back(bar);
}
编辑:好吧,我花了一些时间再次阅读const。我甚至想做什么?我问的原因是因为这句话: 如果在没有const限定符的情况下它没有编译,并且您正在返回一个引用或指向可能是该对象的一部分的指针,那么您的设计就会很糟糕。
我考虑到了这一点,并且没有在const方法中返回引用。这产生了这个错误:
test.cpp:18: error: 'const int Foo::operator[](int)' cannot be overloaded
test.cpp:17: error: with 'int& Foo::operator[](int)'
test.cpp:41: error: prototype for 'const int Foo::operator[](int)' does not match any in class 'Foo'
test.cpp:37: error: candidate is: int& Foo::operator[](int)
摆脱int&amp; Foo :: operator []摆脱了这个错误。我知道我可以创建一个新的访问器来将更改应用到chars_,但我想我会更新它并找出我想要做的事情是否可行。
答案 0 :(得分:5)
您的operator[]
非常规。在您的分配运算符中,为什么不直接访问rhv.chars_
?
E.g。
Foo& Foo::operator=(const Foo &rhv) {
_size = rhv._size;
_chars = rhv._chars;
return *this;
}
答案 1 :(得分:3)
你需要制作两个不同版本的operator[]
,其中一个非const
,就像你现在一样,另一个const
返回const int *
而不是int *
。这样,您就可以在const
和非const
上下文中使用运算符。
顺便说一下,为什么要从operator[]
返回指针而不是引用?从我所看到的情况来看,返回引用更为习惯。
答案 2 :(得分:3)
第一个问题是语法:
int const operator[](int i);
应该是:
int operator[](int i) const;
然而,修复失败,因为std :: map没有const运算符[]。为什么那个人会问?因为它有副作用:
返回对该对象的引用 与特定键相关联。 如果地图尚未包含 这样的对象,operator []插入 默认对象data_type()。 ... 由于operator []可能会插入一个新的 元素进入地图,它不能 可能是一个const成员函数。 注意operator []的定义 非常简单:m [k]是 相当于 (*((m.insert(VALUE_TYPE(K, DATA_TYPE())))。第一))。第二。 严格来说,这个成员 功能是不必要的:它存在 只是为了方便。
取自http://www.sgi.com/tech/stl/Map.html。因此,您将需要使用find函数而不是operator []。
顺便说一句,对于这种实验和研究,我发现在类声明中内联编写所有类函数很方便。简单地说,因为修改类定义的速度更快,尽管一些C ++纯粹主义者将其描述为坏风格。
[编辑:这是一个完整的解决方案]
class Foo {
size_t size_;
std::map<int, int> chars_;
public:
Foo(int *font, size_t size)
: size_(size)
{
// size should be of type "size_t" for consistency with standard library
// in the original example "unsigned int" and "int" was mixed throughout
for (size_t i=0; i < size; ++i)
// Reuse the add function.
Add(font[i]);
}
size_t Size() const {
return size_;
}
void Add(int ch) {
chars_[size_++] = ch;
}
bool operator==(const Foo &rhv) const {
if (&rhv == this) return true;
if (rhv.Size() != size_) return false;
for (size_t i=0; i < size_; ++i)
if (rhv[i] != (*this)[i])
return false;
return true;
}
int& operator[](size_t i) {
assert(i < size_);
return chars_.find(i)->second;
}
const int& operator[](size_t i) const {
assert(i < size_);
return chars_.find(i)->second;
}
Foo& operator=(const Foo &rhv) {
size_ = rhv.size_;
chars_ = rhv.chars_;
return *this;
}
};
int main()
{
std::vector<Foo> baz;
Foo bar = Foo(font, 8);
baz.push_back(bar);
}
答案 3 :(得分:1)
根本不需要赋值运算符。运行每个数据成员的operator=
的自动生成的operator=
应该适用于您的2种数据成员类型(int
和std::map
)。
答案 4 :(得分:0)
你需要
class Foo {
//...
int &operator[](int i);
int operator[](int i) const;
//...
};
和
int &Foo::operator[](int i) {
return chars_[i];
}
int Foo::operator[](int i) const {
return chars_[i];
}
即。 const
位于参数列表之后,而不是返回类型。