想象一下以下场景:
class A
{
int a[50];
int* GetAPtr() { return a; };
};
...
A b;
if(b.GetAPtr()[22] == SOME_RANDOM_DEFINE) do_this_and_that();
这种访问被认为是不好的做法吗? b.GetAPtr()[22]
澄清我的情况:
1.在这种情况下我不能使用new / malloc,数组muste是静态的
这是为了封装使用多个阵列的旧C代码,这些代码非常方便
3.我知道返回一个指针可能会返回一个NULL指针,我们在这里不讨论这个问题
答案 0 :(得分:2)
如果你真的需要这样的const表达式,你可以把它变成一个函数:
class A
{
int a[50];
bool check_this_and_that() { return a[22] == SOME_RANDOM_DEFINE; };
};
...
A b;
if(b.check_this_and_that()) do_this_and_that();
魔术数字一般很糟糕,但在类逻辑中它更可原谅,外人不必看到这一点。
答案 1 :(得分:1)
是的,这是不好的做法,因为你无法知道数组有多长。您可以遵循惯用标准库方法并返回begin
和end
指针,指向第一个和最后一个元素。
class A
{
int a[50];
int* begin() { return &a[0]; };
int* end() { return &a[50]; };
const int* begin() const { return &a[0]; };
const int* end() const { return &a[50]; };
size_t size() const { return 50; } // this could be handy too
};
除了为您提供迭代元素的工具,就像在标准库容器上一样,这允许您检查指向数组元素的任何指针是否为< v.end()
。例如
it* it = b.begin() + 22;
if(it < b.end() && *it == SOME_RANDOM_DEFINE) do_this_and_that();
这使得使用标准库算法变得微不足道:
A b;
// fill with increasing numbers
std::iota(b.begin(), b.end());
// sort in descending order
std::sort(s.begin(), s.end(), std::greater<int>());
// C++11 range based for loop
for (auto i : b)
std::cout << i << " ";
std::endl;
答案 2 :(得分:0)
GetAPtr
是一种访问私有数据成员的方法。现在问问自己b.GetAPtr()[22]
优于b.a[22]
的优势是什么?
封装数据是维护数据成员之间和之间约束的好方法。在您的情况下,a
数组与其长度50
之间至少存在关联。
根据A
的使用情况,您可以构建一个提供不同访问模式的界面:
class A {
int a[50];
public:
// low level
int atA(unsigned i) const { return a[i]; }
// or "mid" level
int getA(unsigned i) const { if(i >= 50) throw OutOfRange(); return a[i]; };
// or high level
bool checkSomething() const { return a[22] == SOME_RANDOM_DEFINE; }
};