4

我需要一种方法来帮助我,在循环中逐个访问名为“comboBox1”、“comboBox2”等的变量。我想更改如下代码:

//proceed comboBox1
//proceed comboBox2
//proceed comboBox3
//proceed comboBox4
//proceed comboBox5
//proceed comboBox6

进入:

for (int i = 1; i < numberOfBoxes; i++) {
    //proceed comboBox(i)
}

我试图找到像“eval”这样的东西,但谷歌没有给出任何匹配的东西。我还尝试使用运算符## 对名称进行预处理,但似乎无法将当前整数值放入宏中。

4

9 回答 9

15

最简单的解决方案是将它们全部放在一个数组和迭代器中:

// I've made up a type, but you get the idea.
std::vector<ComboBox *> combos;
combos.insert(comboBox1);
combos.insert(comboBox2);
combos.insert(comboBox3);
combos.insert(comboBox4);
combos.insert(comboBox5);
combos.insert(comboBox6);

现在您可以迭代组合。主要问题是c++没有反射。所以你不能像在其他语言中那样在运行时生成字符串并获取对象或函数的地址。

编辑:我刚刚看到您正在使用 Qt。在这种情况下,您应该使用:

QList<T> qFindChildren ( const QObject * obj, const QString & name );

或者

QList<T> qFindChildren ( const QObject * obj, const QRegExp & regExp);

这使您可以根据运行时生成的名称获得一个列表。例如:

QList<QComboBox *> combos = qFindChildren(ui, QRegExp("combo[0-9]+"));

然后你可以迭代它!

于 2009-02-19T18:47:53.423 回答
4

我知道如何做到这一点的唯一方法是在代码/动态和数组中创建它们。(不是通过向导)您并不是唯一一个发现 MFC(我认为)向导的缺点的人。

作为替代方案,如果您的资源在资源文件中是连续的(我再次假设类似 MFC 的实现),您可以遍历资源 ID 以获取资源。这假定它们具有连续的资源 ID。我最近用过这个方法。它工作得很好。不确定它是否是您正在寻找的或将与您的 GUI 一起使用。

于 2009-02-19T18:49:30.660 回答
3

C++ 中没有任何方法可以在运行时按名称识别变量。与其使用名称为comboBox1、comboBox2 等的一组离散变量,不如创建一个可以迭代的ComboBox 数组?然后你的循环看起来像:

for (int i = 1; i < numberOfBoxes; i++) {
   doSomething(comboBoxes[i]);
}
于 2009-02-19T18:48:38.167 回答
3

如果您喜欢预处理器技巧,请参阅 Boost.Preprocessor 库:

// Shamelessly copied from the Boost docs, and only slightly
// adapted. (and probably breaking it ;)
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>

#define DO_SOMETHING(z, n, text) BOOST_PP_CAT(text, n)->DoSomething();

BOOST_PP_REPEAT_FROM_TO(0, 3, DO_SOMETHING, comboBox)

会扩展为:

comboBox0->DoSomething();
comboBox1->DoSomething();
comboBox2->DoSomething();
于 2009-02-19T20:23:10.533 回答
2

我使用以下方法进行函数注册,但您可以尝试在您的情况下应用,希望它保证这种不尊重空格的 C 风格解决方法:

#define GET_COMBO_BOX(x,y) x ## y

for (int i = 1; i < numberOfBoxes; i++) 
  GET_COMBO_BOX(comboBox1,i);

这显然不会做你想做的事,因为 i 在编译时确定并且宏在预处理时消耗,但它会让你知道如何预生成函数调用。

这是使用宏连接的更完整示例:

#include<iostream>
#include<string>

using namespace std;


template< class E > struct EnumNames
{
    static const char* const* names;
    static int names_size;
};


#define REGISTER_ENUM( e ) \
    const char* const* EnumNames< e >::names = e ## _names; \
    int EnumNames< e >::names_size = sizeof( e ## _names ) / sizeof( const char* );

enum ElementType { NEURON, SYNAPSE };
const char* const ElementType_names[] = { "N", "S" };
REGISTER_ENUM( ElementType )

enum TokenMainType { EP, IP, NT, AI };
const char* const TokenMainType_names[] = { "EP", "IP", "NT", "AI" };
REGISTER_ENUM( TokenMainType )

template<class E>
ostream& operator <<(ostream& os, const E& e) 
{
    if (e > EnumNames< E >::names_size) 
        cout << "Error" << endl;
    os << EnumNames< E >::names[e];
    return os;

}

template<class E>
istream& operator >>(istream& is, E& e) {
    std::string tmp_e_string;
    is >> tmp_e_string;
    for (int i = 0; i < EnumNames< E >::names_size; ++i) {
        if (tmp_e_string == EnumNames< E >::names[i])
        {
            e = E(i);
            return is;
        }

    }
    cerr << "Fehler: tmp_nntype_string: " << tmp_e_string << endl;
    return is;

}


int main (int argc, char **argv)
{
    ElementType test1(NEURON);
    cout<<string(EnumNames<ElementType>::names[test1])<<endl;

}
于 2009-02-19T18:56:42.387 回答
1

您需要将变量存储在数组中。

例如

mComboBoxes[MAX_COMBOBOXES];

// 初始化

for (int i = 0; i < numberOfBoxes; i++) {
    mComboBoxes[i];
}

请注意,数组具有从零开始的索引。

于 2009-02-19T18:48:42.847 回答
1

使用数组。这就是他们的目的。或容器。

T combobox_array[ N ]; // N comboboxes
for (int i = 0; i < N; ++i)
     process(combobox_array[ i ]); // note array indices are 0 to N-1

或者,使用 STL

vector<T> ca(N);
for_each(ca.begin(), ca.end(), do_something);
于 2009-02-19T18:49:20.007 回答
1

什么是“进行”?

您需要另一个级别的间接性。也许将指向组合框的指针存储在一个向量中,以后可以对其进行迭代。

于 2009-02-19T18:49:43.890 回答
1

有没有理由你不能拥有组合框的数组/向量/列表?

std::vector<ComboBox> comboBoxes;

还是更好地维护一个指向组合框的指针列表?

std::vector<ComboBox*> comboBoxPtrVec;
ComboBox* comboBox1 = new ComboBox();
ComboBox* comboBox2 = new ComboBox();
comboBoxPtrVec.push_back( comboBox1 );
comboBoxPtrVec.push_back( comboBox2 );

for (insigned int i = 0; i < comboBoxPtrVec.size(); ++i)
{
   // process comboBox
   comboBoxPtrVec[i]->DoSomething();
}
于 2009-02-19T18:51:51.143 回答