Reputation: 1317
I have created a class in C++. Each object corresponds with an I/O pin on a microcontroller. I can create an array of the objects and then set each pin to an output with a for loop. I would like to be able to set multiple pins to an output at the exact same time. This can be done with the hardware.
I am trying to create a method that works on an array of objects. You would use it like this:
Pin myPins[] = {0,1,2};
myPins.setOuput();
Basically I want to create a method that works on an array of objects. Is it possible to create a setOuput method like this? If yes, how? Thanks.
Update 1
New non-member method
void setOutput(Pin pins[], int size) {
volatile uint8_t* _DDR = pins[0].getDDR();
uint8_t _offset = 0;
for (int i = 0; i < size; i++) {
_offset |= pins[i].getOffset();
}
DDR_HIGH;
}
I am using the _ in the names so that my existing macro works. Not great but less code.
Upvotes: 0
Views: 314
Reputation: 10069
Nope, you cannot add a method to a classic array the way you intend to. However, you could create a class that inherits from, say, a std::vector<Pin>
, and add methods to it, like this:
class Pins : public std::vector<Pin>
{
public:
void setOutput() { /* your code here */ }
};
That way, using C++11's uniform initialization, you could use a similar syntax:
Pins myPins = {0, 1, 2};
myPins.setOutput();
Edit: as per the comments, subclass a STL container is a quick and dirty solution and not the best idea. You could, however, create your own wrapper class very simply:
class Pins
{
std::vector<Pin> mPins;
public:
Pins (std::initializer_list<Pin> pins) : mPins(pins)
{ }
void setOutput()
{
cout << "Pins in this pinset:" << endl;
for (Pin & p : mPins)
{
cout << "\t" << p << endl;
}
}
};
That works exactly the same:
Pins myPins = {0, 1, 2};
myPins.setOutput();
Upvotes: 2
Reputation: 16156
Most probably your setOutput
member function is reading some possibly multi byte value, changing a bit depending on the pin, and writing it back.
C++ arrays can't have member functions.
To achieve a similar effect, you should split the work your original setOutput
is doing:
Then you can let multiple pins do their bit twiddling before applying the final output.
Example:
Pin::Config cfg = Pin::read_config();
// the following could also happen in a loop over an array.
cfg = pin1.enableOutput(cfg);
cfg = pin4.enableOutput(cfg);
// or pass by reference and mutate, if you
// want a less functional style
// e.g. pinN.enableOutput(cfg)!
Pin::write_config(cfg);
This way you still have good encapsulation, but better control. Then you can write a free function to operate on arrays, vectors or whatever collection of pins, if needed:
template<typename It>
void setOutputPins(It start, It end) {
Pin::Config cfg = Pin::read_config();
for (; start != end; ++start) {
cfg = (*start).enableOutput(cfg);
}
Pin::write_config(cfg);
};
Using it with C arrays:
Pin array[5]; // or a pointer for dynamic arrays
// ...
setOutputPins(array, array + size);
Don't make everything OO. It'll make your life harder.
[...] a function that returns the offset value for each Pin [...]. Then I bitwise or them all together.
So you don't even need that reading step. And since you bitwise or them, you could even do something like this:
Pin::write_config(pin1.output_mask() | pin4.output_mask());
You can make the function generic, too: Or pass a member function pointer:
template<typename It>
void setPins(It start, It end, Pin::Config (Pin::*fn)(void)) {
Pin::Config cfg = 0; // identity for bitwise or
for (; start != end; ++start) {
cfg |= ((*start).*fn)();
}
Pin::write_config(cfg);
};
And the pass a pointer to the member function you want to invoke:
setPins(array, array + size, &Pin::asInput);
Upvotes: 0