对于内置类型的整数数组,请说
int a[10];
int i = 2;
a[i] = 10;
替代地
i[a] = 10;
因为
a[i]
是一个后缀表达式,*(a+i)
或*(i+a)
,因为可以添加的换向属性。
我想为用户定义的类型说明
class Dummy
{
//
};
有可能吗? 如果是,那怎么样? 如果不是那么为什么?
编辑: - 我知道它很丑,但是代码编译后: - g ++ -dumpversion 4.3.3
#include <stdio.h>
#include<iostream>
#include <string.h>
#include <malloc.h>
using namespace std;
int main()
{
string ArrayS[10];
2[ArrayS] = "ADASD" ;
cout << 2[ArrayS] << endl;
return 0;
}
答案 0 :(得分:15)
这是不可能的,因为“operator[]
应该是一个只有一个参数的非静态成员函数”(标准§13.5.5/ 1),所以你不能定义它,使得第一个参数是本地标量类型。
(此外,非静态运算符重载调用被解释为成员调用,因此第一个操作数不能被隐式转换,这与自由函数重载不同。这就是为什么在可能的情况下首选自由函数重载的一个原因。)
无论好坏,index[ object ]
都是确保不会调用operator[]
重载的方法。
“表达式E1[E2]
与*((E1)+(E2))
相同(按照定义)”(第5.2.1节),operator+
只要一个 方不是本机类型。这留下了两个选项漏洞:“数组”必须是一个类,或者“索引”必须是一个类或enum
。
然后,您必须定义代理类型以保存“添加”的结果,该结果定义了operator*
重载。但是,海湾合作委员会不支持这一点。我会更深入地了解其他平台和参考资料。
编辑:啊,§13.6/ 13覆盖5.2.1并声明,为了解释涉及类或枚举类型的表达式,有函数T& operator[](std::ptrdiff_t, T*);
和T& operator[](T*, std::ptrdiff_t);
。就是这样。
答案 1 :(得分:3)
使用C ++,没有什么是不可能的。然而,这是一个可怕的可怕想法。不要这样做。
#include <memory>
#include <stdlib.h>
#include <stdio.h>
void *aligned_malloc( size_t bytes, size_t alignment ) {
void *p = malloc( bytes + alignment ), *pa = reinterpret_cast<void*>( reinterpret_cast<size_t>(p) + alignment &- alignment );
reinterpret_cast<void**>(pa)[-1] = p;
return pa;
}
void aligned_free( void *pa ) {
void *p = reinterpret_cast<void**>(pa)[-1];
free( p );
}
struct SupportReverseIndexer
{
class IndexerReversal
{
static const size_t alignment;
friend struct SupportReverseIndexer;
friend class std::auto_ptr<IndexerReversal>;
struct SupportReverseIndexer* const m_parent;
IndexerReversal(struct SupportReverseIndexer* parent) : m_parent(parent) {}
void* operator new(size_t bytes) { return aligned_malloc(bytes, alignment); }
void operator delete(void* p) { aligned_free(p); }
static struct SupportReverseIndexer* getParent(IndexerReversal* pThis)
{
size_t iThis = reinterpret_cast<size_t>(pThis);
iThis += alignment >> 1;
iThis &= ~(alignment - 1);
return reinterpret_cast<IndexerReversal*>(iThis)->m_parent;
}
public:
operator size_t() { struct SupportReverseIndexer* const parent = getParent(this); return parent->indexer(this-parent->ir.get()); }
};
SupportReverseIndexer() : ir(new IndexerReversal(this)) {}
operator IndexerReversal*() { return ir.get(); }
private:
std::auto_ptr<IndexerReversal> ir;
size_t indexer(size_t index) { printf("Custom operator[] called, index = %i\n", index); return index; }
};
const size_t SupportReverseIndexer::IndexerReversal::alignment = 0x10000 * sizeof(SupportReverseIndexer::IndexerReversal);
int main(void)
{
SupportReverseIndexer sri;
int a = sri[2];
a = 3[sri];
a = (-5)[sri];
return 0;
}
不,真的,不要这样做!!!!!
答案 2 :(得分:2)
a [i] = 10;
我[a] = 10;
因为a [i]是一个后缀表达式,它是*(a + i)或*(i + a),因为加法的交换属性。
是。但是a[i] == i[a] == *(a+i) == *(i+a)
是因为C中的符号a[i]
是后一指针算术的syntactic sugar。关键字在这里“在C”。大型C ++试图从指针算法中分离出来。因此a[i]
仅作为语法糖支持POD以向后兼容C.但是这对任何C ++对象都不起作用,因为操作[]
具有明确的语义指定和它不允许类似C语法的技巧。
最后,不要这样做。诀窍是旧时代的一个模糊残余,并没有一个很好的理由被转世。
答案 3 :(得分:2)
完全不可能。 Potatoswatter correctly points out您无法定义任何运算符,例如operator[](int, T)
,因此无法对左侧的整数进行重载。
但请考虑这是有效的:
struct foo
{
operator const foo*() const
{
return this;
}
};
int main()
{
foo f;
5[f]; // UB
}
有没有办法利用这个?号:
5.2.1订阅
后缀表达式后跟方括号中的表达式是后缀表达式。其中一个表达式应具有“指向T的指针”类型,另一个表达式应具有枚举或整数类型。结果是类型为“T”的左值。类型“T”应该是完全定义的对象类型.56)表达式E1[E2]
与*((E1)+(E2))
相同(根据定义)。
E1
是整数类型,E2
必须是指针类型。所以我们不能在那里注入用户行为。
唯一剩下的就是+
和*
。我们不能为整数类型和指针更改operator+
,因为它是由语言定义的。 E1 + E2
的结果将成为指针,我们也无法为指针定义operator*
。
因此,注入用户定义的行为是不可能的。
答案 4 :(得分:0)
您需要定义Dummy::operator[](const Dummy& ref)
以展示所需的属性。例如:
#include <iostream>
class dummy
{
public:
int operator[](const dummy& ref) { return 0; }
};
int main(int argc, char *argv[])
{
dummy d1, d2;
std::cout << (d1[d2] == d2[d1] ? "Yes" : "No");
}
当然这可能不是你想要的,但是棘手的一点是用你必须定义的东西替换return 0;
和可能的返回类型,并且满足你的意图。 / p>
为什么你想要这个?这只是一种心理锻炼吗?
答案 5 :(得分:0)
如果Dummy可以隐式地转换为整数,那么声明并用作数组的任何Dummy都将以相同的方式工作。