如何将一个或多个(未定义的数字)参数传递给函数?

时间:2018-02-06 14:19:43

标签: c++ function c++11

我为wiringPi编写了一个包装类。通过将一个或多个参数传递给函数,我希望能够通过调用函数一次来操作多个LED。传递参数的数量不应受到限制,即它可以是1,2,3或更多。这是我目前的职能:

typedef enum{LED1 = 12, LED2 = 13, LED3 = 14, LED4 = 15}LED;

void Led::on(LED led)
{
    digitalWrite(led, HIGH);
}

我可以这样做吗?怎么样?

我想我可以使用重载但是如果参数的数量是未定义的(即,它可以是1或7)怎么办?

5 个答案:

答案 0 :(得分:4)

一个位域?

如果您有少量LED并且您使用不同位定义其值

typedef enum {LED1 = 1, LED2 = 2, LED3 = 4, LED4 = 8};

或更好(确保tu仅使用两个值的幂),如user2079303所建议的(谢谢!),

typedef enum {LED1 = 1 << 0, LED2 = 1 << 1, LED3 = 1 << 2, LED4 = 1 << 3};

你可以将一个or-value的leds传递给Led::on()

on(LED1 | LED2 | LED4);

并在on()内检查单个位

void Led::on (int leds)
 {
   if ( 0 != (leds & LED1) )
    /* do something for LED1 */;

   if ( 0 != (leds & LED2) )
    /* do something for LED2 */;

   // ...
 }

答案 1 :(得分:2)

使用可变参数的示例。这可能是最有效的方法,因为所有工作都是在编译时完成的。

enum LED {LED1 = 12, LED2 = 13, LED3 = 14, LED4 = 15};
constexpr const int HIGH = 1;
void digitalWrite(LED, int);

template<class... LED>
void on(LED... leds)
{
    (digitalWrite(leds, HIGH), ...);
}

void foo() {
    on(LED1, LED2, LED3);
    on(LED4);
}

https://godbolt.org/g/b22y5N

注意:上述语法需要c ++ 17

C ++ 11兼容版本:

enum LED {LED1 = 12, LED2 = 13, LED3 = 14, LED4 = 15};
constexpr const int HIGH = 1;
void digitalWrite(LED, int);

void on(LED leds)
{
    digitalWrite(leds, HIGH);
}

template<class... LEDs>
void on(LED led, LEDs... leds)
{
    on(led);
    on(leds...);
}

void foo() {
    on(LED1, LED2, LED3);
    on(LED4);
    on(LED1, LED2);
}

https://godbolt.org/g/Js13vi

答案 2 :(得分:1)

对于参数的同类集合(即相同类型的对象),在C ++中执行此操作的惯用方法是传递一对迭代器。第一个迭代器到一个范围的开头,第二个迭代器到结尾(一个是结束的,确切地说)。

虽然可以编写一个模板来处理所有输入迭代器,但一个简单的选择是支持一个特定的迭代器。迭代器的选择取决于您选择存储对象的数据结构。例如,您可以使用指针参数来支持数组:

        string strSQL = "SELECT DISTINCT PRODUCT_LINE, MODEL_YEAR, ORDER_DATE "
                    + "FROM ORDER_BANK "
                    + "WHERE ((PRODUCT_LINE = ?) AND (MODEL_YEAR = ?) AND (ORDER_DATE BETWEEN ? AND ?))";

        Command = new OleDbCommand(strSQL, Connection);
        Command.Parameters.AddWithValue("PRODUCT_LINE", strprodline);
        Command.Parameters.AddWithValue("MODEL_YEAR", strModelYear);
        // ??? WHAT DO I DO HERE FOR "(ORDER_DATE BETWEEN ? AND ?)"

答案 3 :(得分:0)

您可以为此传递LED s的容器。例如以下使用std::initializer_list

typedef enum{LED1 = 12, LED2 = 13, LED3 = 14, LED4 = 15}LED;

void Led::on(std::initializer_list<LED>& leds)
{
    for (auto& led : leds) // Since this is tagged C++11
    {
        digitalWrite(led, HIGH);
    }
}

调用此函数将非常简单:

Led::on({LED1, LED2, LED3});

使用初始化列表很好,因为它轻巧且易于使用。 这是一个最小的工作example

答案 4 :(得分:0)

有几种方法可以实现这一目标。

最重要的是使用上面评论中提到的std::vector

#include <vector>

void Led::on(std::vector<LED>) {
    for (LED l : leds) {
        digitalWrite(l, HIGH);
    }
}

std::vector<LED> leds = {LED1, LED2};
// you realize you need more
leds.push_back(LED3);

Led::on(leds);

您可以使用variadic functions。我既不会推荐也不会解释这个。我已经提供了一个帮助你的链接。