I have an array of structs -
struct MagicalUnicornBullets {
PS2Sprite SparklyUnicornBullet();
bool onscreen;
};
MagicalUnicornBullets MagicalUnicornBullets[25];
I want to loop through the array, and initialise the contents of the struct.
Obviously, this is just the case of a for loop, and for the bool it's simply onscreen = false; but how would I initialise the SparklyUnicornBullet?
Right now my code is -
MagicalUnicornBullets[i].SparklyUnicornBullet.ScaleAbsolute(4,4);
I'm well aware this is wrong - but how do I access the class functions when they're within the Struct?
Realize that SparklyUnicornBullet is actually a member function which returns a PS2Sprite object. This returned PS2Sprite has a member function ScaleAbsolute which you want to call. So your code above is nearly correct. You are simply missing ()'s:
MagicalUnicornBullets[i].SparklyUnicornBullet().ScaleAbsolute(4,4);
That said, there's a number of things that's bad with your code. For one, you are declaring an array that has the same name as an object:
MagicalUnicornBullets MagicalUnicornBullets[25];
I think this is allowed, but it is so evil and malmotivated that I can't even say that for certian, because I would reject any such code regardless of it's motivation or legality. You should give the array a different name:
MagicalUnicornBullets bullets[25];
Next, your initialization loop is unneeded. The code:
MagicalUnicornBullets MagicalUnicornBullets[25];
creates a C-style array of 25 MagicalUnicornBullets by calling each one's default constructor. So the easiest thing to do is to simply provide a default constructor that does what you want:
struct MagicalUnicornBullets {
MagicalUnicornBullets();
// ...
};
MagicalUnicornBullets::MagicalUnicornBullets()
: onscreen(false)
{
SparklyUnicornBullet().ScaleAbsolute(4,4)
}
Now there's no need for a loop at all. All 25 will be constructed and initialized the way you want.
Finally, usually in C++ it's advantagerous to not use a C-style array at all, but a collection class such as std::vector.
Related
I have a class functionCombiner which constructor looks like this
FunctionCombiner::FunctionCombiner(std::vector<std::shared_ptr<valuationFunction>> Inner_) : Inner(std::move(Inner_)), valuationFunction("", 0) //<- Needs to initalize itself even though it gets all data from inner functions.
{
}
In my main class I'm calling it like this:
vector<std::shared_ptr<valuationFunction>> combinedStillFrontFunctions{ stillFrontStock, stillFrontEuropeanCall };
std::shared_ptr<valuationFunction> StillFrontFunctions = std::make_shared<FunctionCombiner>(combinedStillFrontFunctions);
What I would like to be able to do is reduce that to one line by constructing it in place like so
std::shared_ptr<valuationFunction> StillFrontFunctions = std::make_shared<FunctionCombiner>({ stillFrontStock, stillFrontEuropeanCall });
Which the compiler doesn't like. Is there a way to make this work? This works obviously:
FunctionCombiner StillFrontFunctions({ stillFrontStock, stillFrontEuropeanCall });
But I need it to be a shared pointer.
(Shorting some names to make the example readable w/o horizontal scrollbars. You should consider doing the same...)
Passing {x,y} to make_shared() is attempting to forward a brace-enclosed initializer list, not to initialize the value in the shared pointer, but the temporary object its constructor takes. It's not something that can be forwarded since it's not a full expression on its own. So make a temporary vector with those values:
... = make_shared<FunComb>(vector<shared_ptr<valFun>>{FS, FEC});
Another approach may be to change FunComb's constructor to be a (or add a new) variadic constructor, removing the need to pass in a vector just to hold the inputs.
Consider an array of function pointers within a class in c++14:
class myClass {
myClass();
void (* myFunctions [5])();
}
This array will be populated in other parts of the code, and it is not guaranteed that the array will actually hold as many function pointers as it can (5 in the example). So before calling any of the functions referred to by the array i'd need to check whether the pointer I'm trying to use actually stores something. My idea was to compare the pointer against nullptr, and assume that it points to a valid function if the test fails, i.e. in some function of that class:
if(myFunctions[x] == nullptr) {
// Handle error
return;
}
// Use myFunctions[x]
I was wondering if I need to initialize the array before making that kind of speculation. How is this array initialized if I only write the above two lines of code? Can I assume something like myFunctions[x] == nullptr is true in that case? Or do I need to do an explicit initialization like the following one?
for(int i = 0; i < dimension; i++)
myFunctions[i] = nullptr;
I've found the zero initialization page on cppreference.com, but as I'm learning c++ and I'm still very unexperienced I wasn't able to understand whether this applies in my case. I've also tried to test the pointers by printing their value without assigning any function address and got 0 0 0 0 0, but I don't think the result is reliable: this program is for a microcontroller, and it's possible that the "garbage" values on the stack are all 0s since it is emptied during each code upload.
I don't think that you have to initialize the array, although I'd encourage you to do that. The reason why the array is default-initialized in your case is because you provide a constructor and do not mention the data member in the initializer list (cf. cppreference/default initialization):
Default initialization is performed in three situations:
...
3) when a base class or a non-static data member is not mentioned in a
constructor initializer list and that constructor is called.
Hence, default initialization will take place.
Anyway, in order to express that you rely on a data member to be "zero" without enforcing in other ways that non-initialized entries will not be accessed, I'd make the initialization explicit, e.g.
class myClass {
myClass();
void (* myFunctions [5])() = { };
}
I have a global two dimensional array holding a number of structs. From inside a function I try to change it's members like this:
struct ControlPin {
int pin;
int previousValue;
};
ControlPin controls[CHANNELS][MULTIPLEXERS];
void readControlInput(int channel, int multiplexer) {
ControlPin control = controls[channel][multiplexer];
control.previousValue = analogRead(control.pin);
}
If i print out control.previousValue inside readControlInput() I can verify that it has changed, but after getting out of the function scope, the change is gone. How can I get a reference to the struct instead of copying it? I assume that's what happening, but I cant see why. I know that when you pass a value as a parameter to a function it is actually a copy, but here I'm accessing the global array directly?
I'm used to Java so this is a bit confusing to me.
In Java all objects are (IIRC) references. In C++ the default is that objects are values. When you do
ControlPin control = controls[channel][multiplexer];
you copy the "value" in controls[channel][multiplexer], then when you modify control you only modify the local value, and not the value in the array.
The simplest option is to explicitly say that control is a reference, by using the ampersand (&) when declaring the variable:
ControlPin& control = controls[channel][multiplexer];
// ^
// |
// Note ampersand here
That tells the compiler that control is a reference and then initializes it to reference the object (value) at controls[channel][multiplexer].
On an unrelated not, C++ have no bounds-checking. If you access an array out of bounds the compiler will happily allow it, but it will lead to undefined behavior at run-time. You need to do bounds-checking yourself if you want to avoid weird problems. It doesn't have to be in the function, but it needs to be done somewhere.
You're not accessing the array directly, this works exactly like if you had passed the element to a function:
void readInput(ControlPin control)
{
control.previousValue = analogRead(control.pin);
}
void readControlInput(int channel, int multiplexer) {
readInput(controls[channel][multiplexer]);
}
You can tell from the types - ControlPin means the same thing regardless of whether it is a local variable or a parameter.
In C++, variables that contain class instances always contain class instances and not some kind of "reference" to them, so just like when calling a function,
ControlPin control = controls[channel][multiplexer];
creates a copy of the array element, and
control.previousValue = analogRead(control.pin);
modifies that copy.
The simplest fix is to write it in one line:
controls[channel][multiplexer].previousValue = analogRead(control.pin);
You can also use a reference variable (which is different from Java's "references") to refer to the array element itself:
ControlPin& control = controls[channel][multiplexer];
control.previousValue = analogRead(control.pin);
This is most useful if you need to do more than one thing with the same element - it's both more readable and more resilient to errors than duplicating the indexing.
Say I have a header file that looks like:
# filename: header.h
class myclass
{
public:
int myVariable; # arbitrary member variable
foo(); # arbitrary function
myclass() # default constructor
}
Now lets say I want to implement my constructor [ myclass() ] in some .cpp file:
Can I do something like create an array, of objects, ints, anything - just some array.
And then can I loop through that array and fill it up all from within my constructor definition?
The reason I ask is because I want my arbitrary member function foo() to be able to change this array. This leads to the problem - am I passing an object of myclass into foo [ foo(myclass myclassObject) ?
Or do I pass this object's array into foo() ?
Any clarification on this would be much appreciated. I tried to make the example as non-specific to a certain case as possible, but still descriptive enough for everyone to understand the problem. Thank you!
Yes, you can create and "fill up" an array from within the constructor so it can be used by foo. Indeed, that is the purpose of the constructor (to set up everything for you).
Do note that if you want foo() to be able to use the array, you must make the array part of the class definition.
myclass.h
class myclass {
private:
int* arr; // declared on the "heap"
public:
foo();
myclass(int arraySize);
};
myclass.cpp
#include "myclass.h"
#include <stdio>
myclass::myclass(int arraySize) :arr(new int[arraySize]) {}
myclass::foo() {
// prints the elements of the array we declared earlier
for (int i = 0; i < 5; i++) {
std::cout << arr[i] << std::endl;
}
}
Your constructor can indeed create an array - the question is what happens to that array after the constructor returns.
A reasonable approach is to save it on the heap - i.e. create the array with new[] - but that means you'll need to keep a pointer to the array to access it afterwards. Easiest way to do that is to add a pointer object to your class member data. foo() can then access the array using that pointer. Unfortunately, you must use either custom copy constructors, assignment operators and destructor (google Rule of Three) or a smart pointer to ensure proper copying or sharing and destruction of the array.
Your question implies to me that you don't just want an array data member, which is of course the easiest solution. Disadvantages with that are that the array size must be chosen at compile time, whereas heap based arrays can be sized at runtime.
If you create it on the stack, then it will leave scope and be inaccessible afterwards (any attempt to access it via pointers or references set while it was in scope will result in undefined behaviour).
It's also possible for a constructor to populate data in a static array, but clearly the array's lifetime is then independent of any single object instance of the class. You've talked about the constructor creating the array so presumably don't want to do this.
Well, I'm gonna be pretty straightforward here, I just have a piece of code in c++ which I'm not sure I really understand and need some help with.
Ok, to simplify lets just say I have a class that is defined like this: (the real class is a little bit more complicated, but this is what matters)
class myClass : public Runnable {
Semaphore *m_pMySemaphore;
__Queue<Requests> *m_pQueue;
Request m_Request;
VetorSlotBuffer *m_vetorSlotBuffer;
}
Up to here nothing is wrong, myClass is just a regular class which has 3 members that actually are pointers to other classes and an object of the class Request, the implementation of those classes not being important for my point here.
Then when this person implemented the constructor for myClass he or she did this:
myClass::myClass() : m_pMySemaphore(0), m_pQueue(0), m_vetorSlotBuffer(0) {
}
It's pretty evident that those three variables are treated like that by the constructor because they are pointers, am I right? but what kind of syntax is that? am I setting the pointers to null by doing that? I've seen a little bit of c++ already but never found something like that.
And secondly, what's the deal with the ":" after the constructor declaration? that I've seen but never took the time to investigate. Is this like an inner class or something?
Thank you very much in advance.
Nelson R. Perez
This is an initialization list
And it's the recommended way to initialize your members
It's member's initialization on object creation, called initialization list.
You can't initialize them elsewhere, say:
class X {
int i = 0; // error bad syntax
}
Neither in constructor by use of assignment, if they're const :
class X {
const int i;
X(){
i = 0; // error it's a const
}
}
So the c++ guys made up that syntax!
Yes, those pointers are being initialized to NULL. The key thing here is that they are initialized, as opposed to assigned. I.e.:
myClass::myClass()
: m_pMySemaphore(0), // initialized to 0
m_pQueue(NULL) // initialized to NULL (preferable to 0)
// no initializer for m_Request - uses default constructor
// no initializer for m_vectorSlotBuffer
{
// at this point, the object is entirely initialized, and can be used.
// this next line ASSIGNS to the member
m_vectorSlotBuffer = 0;
}
What happens to m_vectorSlotBuffer, is that it is initialized, and then assigned, in two separate steps. By doing it like m_pQueue, we save a step, and initialize properly. This becomes very important when we want to use non-default constructor, or if we want to initialize const members.
Also, the : after the constructor () is what begins the initialization section, before we get to the { where we enter the body of the constructor.
Finally, NULL is not guaranteed to be 0. NULL is portable, but most architectures use 0 as NULL.
EDIT: 0/NULL distinction is not meaningful anymore. Just pick one and be consistent.
Yes, pointers set to 0 are pointers set to null.
The : syntax for constructors is called initialization lists. It's used here for initializing member fields in a simple, direct manner. Should be easy to google with the proper terminology.