任何方法调用方法与数组符号而不是括号?



在一个大型c++项目中,我正在将结构体更改为类,但试图尽量减少对使用该结构体的任何代码的更改,以使其易于恢复或重新应用更改。

结构体声明如下:

struct tParsing {
char* elements[23];
};

下面是当前版本的类声明(注意,为了清晰起见,我在声明中显示了elements方法体,但实际代码在CPP文件中单独显示):

class tParsing
{
public:
tParsing();
~tParsing();
void clear();
char* elements(int index) {
if (index < 0 || index > 22) return NULL;
return fElements[index];
};
private:
char* fElements[23];
};

parsingInstance->elements[0]

代码的其他部分有许多类似于以下的情况来从结构体中获取一个元素:为了满足我最小化变化的目标,是否有任何方法可以使类,以便elements方法可以使用数组符号(而不是括号)调用来传递索引参数,所以像上面这样的代码无论tParsing是结构体还是类都可以工作?

在tParsing中简单地引入operator[]会破坏现有的代码,比如parsingInstance->elements[0]——但是如果成员提供了这个操作符呢?

class tParsing
{
class Elements
{
public:
char*& operator[](size_t index);
char const* operator[](size_t index) const;
private:
char* data[23];
};
public:
Elements elements;
};

现在Elements类将管理数组,并且您保留与现有代码的兼容性。您可能会弃用操作符,以便将新代码推送到新的API(如果计划,那么您将在tParsing中添加一个额外的operator[]转发到Elements::operator[])。

根据你的需要,你可以将Elements的进一步接口保持为私有,并将tParsing声明为友类,以允许所有其他类仅通过后一个类访问数组。

然后有一天,当您期望所有instance->elements[...]调用都已消除时,您可以再次删除嵌套类,并将数据管理直接留给tParsing

这是一种丑陋的hack,但你可以保持fElements通过制作一个内部类包装器重载operator[]访问fElements,例如(用一些测试代码来验证它的工作):

#include <iostream>

class tParsing
{
public:
tParsing() : fElements{ new char[4]{'a', 'b', 'c', ''} }, elements(fElements) {}
~tParsing();
void clear();
private:
char* fElements[23];
class elements_proxy
{
public:
elements_proxy(char* elements[23]) : elements(elements) {}
char* operator[](int index) {
if (index < 0 || index > 22) return NULL;
return elements[index];
}
private:
char** elements;
};

public:
elements_proxy elements;
};
int main(int argc, char **argv) {
auto parsingInstance = new tParsing{};
std::cout << parsingInstance->elements[0] << std::endl;  // Outputs abc
}

上网试试!

我确信有方法可以简化它(我的高级c++生锈了),所以我欢迎评论中的任何建议(内存泄漏是故意的,只是试图最小化工作来做一些与OP规范相匹配的有用的事情,而不实现实际的解析)。

希望这对你有帮助:)

#include <cstddef>
#include <array>
#include <iostream>
class tParsing {
public:
tParsing(): elements{this}, fElements{} {}
tParsing(const tParsing& other): elements{this}, fElements(other.fElements) {}
tParsing(tParsing&& other): tParsing(other) {}
tParsing& operator=(const tParsing& other) {
fElements = other.fElements;
return *this;
}
tParsing& operator=(tParsing&& other) { return operator=(other); }

struct proxy_t {
tParsing* p;
char*& operator[](std::size_t index) { return p->fElements[index]; }  
char* const & operator[](std::size_t index) const { return p->fElements[index]; }
} elements;

private:
std::array<char*, 23> fElements;
};

int main() {
auto p = new tParsing;
p->elements[0] = new char('x');
std::cout << *p->elements[0] << std::endl;
}