简体   繁体   English

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

[英]How to passing one or more (undefined number) parameters to a function?

I'm writing a wrapper class for wiringPi . 我正在为wiringPi编写一个包装类。 I would like to be able to manipulate more than one LED, by calling the function once, by passing one or more parameters to the function. 通过将一个或多个参数传递给函数,我希望能够通过调用函数一次来操作多个LED。 The number of passed parameters should not be limited, ie, it can be 1, 2, 3, or more. 传递参数的数量不应受到限制,即它可以是1,2,3或更多。 Here is my current function: 这是我目前的功能:

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

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

Can I do this? 我可以这样做吗? and how? 如何?

I think I can use overloading for this but what if the number of parameters is undefined (ie, it can be 1 or 7)? 我想我可以使用重载但是如果参数的数量是未定义的(即,它可以是1或7)怎么办?

A bitfield? 一个位域?

If you have a little number of leds and you define their values using different bits 如果你有少量的LED,你可以使用不同的位来定义它们的值

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

or better (to be sure tu use only power of two values), as suggested by user2079303 (thanks!), 或更好(确保tu仅使用两个值的幂),如user2079303所建议的(谢谢!),

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

you can pass a or-value of leds to Led::on() 你可以将一个or值的leds传递给Led::on()

on(LED1 | LED2 | LED4);

and check, inside on() , single bits 并检查,在内部on() ,单个位

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

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

   // ...
 }

Example using variadic. 使用可变参数的示例。 This is likely the most efficient way to do this as all the work is done in compile time. 这可能是最有效的方法,因为所有工作都是在编译时完成的。

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 https://godbolt.org/g/b22y5N

Note: you need c++17 for above syntax 注意:上面的语法需要c ++ 17


C++11 Compatible version: 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 https://godbolt.org/g/Js13vi

For a homogeneous collection of parameters (ie objects of same type), the idiomatic way to do this in C++ is to pass a pair of iterators. 对于参数的同类集合(即相同类型的对象),在C ++中执行此操作的惯用方法是传递一对迭代器。 First iterator to the beginning of a range, and the second iterator to the end (one past the end, to be exact). 第一个迭代器到一个范围的开头,第二个迭代器到结尾(一个是结束的,确切地说)。

Although it would be possible to write a template to handle all input iterators, a simple choice is to support one particular iterator. 虽然可以编写一个模板来处理所有输入迭代器,但一个简单的选择是支持一个特定的迭代器。 The choice of iterator depends on what data structure in which you've chosen to store the objects. 迭代器的选择取决于您选择存储对象的数据结构。 For example, you could support arrays by using pointer arguments: 例如,您可以使用指针参数来支持数组:

void Led::on(LED* begin, LED* end)
{
    std::foreach(begin, end, [](auto& led) {
        digitalWrite(led, HIGH);
    }):
}

You could pass a container of LED s for this. 你可以为此传递一个LED容器。 Such as the following using std::initializer_list : 如下面使用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);
    }
}

Calling this function would be as simple as: 调用此函数将非常简单:

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

Using an initializer list is good since it lightweight and simple to use. 使用初始化列表很好,因为它轻巧且易于使用。 Here is a minimal working example . 这是一个最小的工作示例

There are a couple of ways to accomplish this. 有几种方法可以实现这一目标。

The most trivial is to use std::vector as mentioned in the comments above. 最琐碎的是使用上面评论中提到的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);

You can use variadic functions . 您可以使用variadic functions I will neither recommend this nor explain this. 我既不会推荐也不会解释这个。 I have included a link to help you though. 我已经包含了一个帮助你的链接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM