Arduino C++ Declare array of objects with parameters in constructor [duplicate] - c++

This question already has answers here:
Object array initialization without default constructor
(14 answers)
Closed 3 years ago.
I only want to declare an array of objects of class control with size of 5. The contents of the specific objects will be filled afterwards.
class control {
public:
control(char* controlName) {
name = controlName;
}
private:
char* name;
};
void setup() {
control humidityControl("humidityControl");
// Problem: Declare an array controlArray with the size of 5 and the name "controlArray"
control controlArray[5]("controlArray"); // Error: no matching function for call to 'control::control()'
control controlArray("controlArray")[5]; // Error: expected ',' or ';' before '[' token
}
void loop() {
}
I'm using C++ on my Arduino. I'd appreciate every tipp how to fix this. Thanks!

Your problem is that you're mixing the declaration of an array (the square brackets) with a call to the constructor. This SO answer clarifies it: https://stackoverflow.com/a/1598409/2881667.
What you want to do is this:
void setup() {
control controlArray[5] = {"controlArray", "controlArray", "controlArray", "controlArray", "controlArray"};
}
Notice how you have to include the argument to the constructor 5 times. To avoid that, you have two options:
Use a default constructor:
control(char* controlName = "controlArray");
Might work for you, but only if you plan on initializing all arrays with the same value.
If using gcc, you can use its extension to initialize it like this:
control controlArray[5] = {[0 ... 4] = "controlArray"};
But this will only work with gcc, so not so good for portability.
Also, unrelated to your question - I think you probably meant to copy the string, and not store the pointer in your class, so you should use something like strncpy in the constructor, instead of just assigning to name, and you'll have to preallocate storage for name in that case (either declare it as a char array, like char name[255];, allocate space for it in the constructor, or use std::string to make it all easier).

Related

Explaining classes [duplicate]

This question already has answers here:
What is this weird colon-member (" : ") syntax in the constructor?
(14 answers)
Closed 7 years ago.
I have a couple of syntax questions that I'm sure most people could answer but this is all foreign to me and I worked through a class tutorial but it left a few questions unanswered.
This code is the declaration line of a class function and inside the parenthesis are the values to be passed. correct?
void HwCounter_IVBNHSX_IMC::SetRegisterLocations(int bus, int ha, int chan, int counterNumber)
{
_ha = ha;
_chan = chan;
_counterNumber = counterNumber;
_bus = bus;
}
In this example what does the additional semicolon at the end enable? Where would I be looking to see what the counterNumbers are associated with?
HwCounter_IVBNHSX_IMC::HwCounter_IVBNHSX_IMC(int hwType, const char* pName) : HwCounterBase(pName)
{
_counterNumber = 0;
_currentConfig = 0;
_hwType = hwType;
}
I'm unable to post the entire source code sorry and I know that makes it more difficult but any help would be appreciated.
This code is the declaration line of a class function and inside the
parenthesis are the values to be passed. correct?
Yes, it is, being understood that the function has to be first declared inside the class.
In this example what does the additional semicolon at the end enable?
HwCounter_IVBNHSX_IMC::HwCounter_IVBNHSX_IMC(..) is a constructor for the class HwCounter_IVBNHSX_IMC.
The : is followed by a list of mem-initializer, a special form of initialization of data members and of the base class if necessary. For example HwCounterBase(pName) means that the data member (or the base class) HwCounterBase is intialized by calling its constructor with the value pName.
This:
void HwCounter_IVBNHSX_IMC::SetRegisterLocations(int bus, int ha, int chan, int counterNumber)
{
...
}
is the definition of a function. (The declaration is something else, and to learn the distinction you should start with a simpler example.) Its name is SetRegisterLocations, it is a member of the class HwCounter_IVBNHSX_IMC, it takes four arguments (all int), and it returns nothing (void).
This:
HwCounter_IVBNHSX_IMC::HwCounter_IVBNHSX_IMC(int hwType, const char* pName)
{
...
}
is similar, but it is a constructor. The name of the function is the same as the name of the function, and it has no return type (not even void).
This:
HwCounter_IVBNHSX_IMC::HwCounter_IVBNHSX_IMC(int hwType, const char* pName) : HwCounterBase(pName)
{
...
}
is the same, but it has an initializer list (consisting of only one initializer) which sets the value (or calls the constructor) of a member variable (HwCounterBase).
Where would I be looking to see what the counterNumbers are associated
with?
The rest of the code.

Char array initialisation in class

I am trying to unit test a C++ application that I am building and I'm having an issue initializing the array when used in a class. I've tried alot of different methods of loading this information, the only ones that work are inefficient / not suitable.
Here is the hex array that I have (randomised the parts)
0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10
And header file for my unit test:
class MessageParsingTest : public CPPUNIT_NS::TestFixture {
CPPUNIT_TEST_SUITE(MessageParsingTest);
CPPUNIT_TEST(testIdentifyFirstMessageType);
CPPUNIT_TEST_SUITE_END();
public:
MessageParsingTest();
virtual ~MessageParsingTest();
void setUp();
void tearDown();
private:
void testIdentifyFirstMessageType();
void testIdentifySecondMessageType();
// data members for the hex array
unsigned char firstMessage[1500];
};
Then in my test case setUp function;
void MessageParsingTest::setUp() {
firstMessage = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
}
That it my latest failed attempt, it says its not valid during compilcation, as I expected, but at this point I was trying anything.
I've also tried things like (all in setUp function)
firstMessage << "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
firstMessage[1500] = "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
and a few other crazy ways, Does anyone know the proper way to load this data? the only way I've had it working so far is with either no data member declaration and straight up defining it and initializing in one line (but then I cant access in the test cases) or doing it one by one like firstMessage[0] = 0x24; etc.
I understand that there will be a simple, proper way of doing this and considering what the application actually does, this part should be the easiest.
You have few options:
Initialize arrays in constructor MesssageParsingTest using syntax : firstMessage{0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10}
in initializer list.
Create static const array containing your message, and either copy it to member variable using memcpy, or use static member and get rid of firstMessage member variable.
Declare const static member in .h inside class definition:
static const unsigned char kFirstMessage[];
and define + initialize it in .ccp
const unsigned char MessageParsingTest::kFirstMessage[] = "\0x24\0x54\0x3b\0x72\0x8b\0x03\0x24\0x29\0x23\0x43\0x66\0x22\0x53\0x41\0x11\0x62\0x10";
I would prefer static const member if you do not intend to modify this array later, since it makes the intention cleaner.
Here is one way to do it.
void MessageParsingTest::setUp()
{
unsigned char x[] = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
::memcpy(firstMessage, x, sizeof(x));
}
If you are using C++11, you can also initialize the firstMessage in the class member initialization list as
MessageParsingTest::MessageParsingTest() :
firstMessage{0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10},
...
You can use a temporary buffer and then copy into you member as this:
void MessageParsingTest::setUp() {
unsigned char tmp[1500] = {0x24,0x54,0x3b,0x72,0x8b,0x03,0x24,0x29,0x23,0x43,0x66,0x22,0x53,0x41,0x11,0x62,0x10};
memcpy(firstMessage, tmp, 1500);
}

When to use "this" pointer in member function [duplicate]

This question already has answers here:
When should I make explicit use of the `this` pointer?
(12 answers)
Closed 8 years ago.
Background:
I am reading code written by someone else, and I am fairly new to C++ programming. When I look at the classes written by that person, and the corresponding member functions, I get confused with the usage of the this pointer. In some member functions this is used and in others not.
Why is that the case?
I know it is a very common confusion for the ones who start doing C++ recently.
Code Snippets:
The class:
class InitTable {
public:
InitTable();
virtual ~InitTable();
void clearTable();
void addEntry(std::string sumoID);
void deleteEntry(std::string sumoID);
InitEntry* getEntry(std::string sumoID);
IPv4Address getEntryIPaddress(std::string sumoID);
protected:
std::map<std::string, InitEntry*> table;
};
Member function (with this):
void InitTable::clearTable()
{
this->table.clear();
}
Member function (without this):
void InitTable::deleteEntry(std::string sumoID)
{
InitEntry* ie = getEntry(sumoID);
if (ie != NULL)
{
table.erase(sumoID);
delete ie;
}
}
Question:
Note that in void InitTable::clearTable() , this->table.clear() is used and in void InitTable::deleteEntry(), table.erase() only table without this is used.
void InitTable::clearTable()
{
table.clear(); // no "this"
}
What is the trick in here? What would be the behaviour if this->table.erase() would be used instead.
void InitTable::deleteEntry(std::string sumoID)
{
InitEntry* ie = getEntry(sumoID);
if (ie != NULL)
{
this->table.erase(sumoID); // "this" added
delete ie;
}
}
As I said, I'm a bit of n00b so a thorough description with minimal example would be very helpful.
It is never required inside a normal function, unless there is a parameter with the same name as a member. In a constructor you can use an initalizer list to prevent ambiguity. The use of a this pointer might be required when you use templates.

How to store objects of different class in an array of pointers

I have 3 classes. DrawGameComp' and 'GameComp' where 'GameComp' is the base class of 'DrawGameComp'. I have an array of pointers in Game class which is the controlling class. '
GameComp * components[]; From the main I have to create a dynamic instance of Game and store add new objects of GameComp and DrawGameComp to the array of pointers of type GameComp.
Game Game1(2);
Game1.Add(new GameComponent);
Game1.Add(new DrawableGameComponent);
I'v done this part in the main. Because from the main I have to invoke Add passing object as the parameter. When i store these objects I also want assign an id of 1 to the first object and an id of 2 to the second object. How can i include that too.
The Add() function of my Game class is as follows
void Game::Add(GameComponent*)
{
components[0]=GameComp;
componentCount++;
}
but it give me error. I have tried so hard. But I couldn't. Also how do I invoke the Display() member function of these objects in the Array? is it this way?
components[0]->Display();
The Add method should look like:
void Game::Add(GameComponent* comp)
{
components[componentCount++] = comp;
}
Make sure you zero out componentCount in the constructor.
Using the array:
components[i]->DoSomething();
1) You probably meant to write the following:
void Game::Add(GameComponent* comp)
{
components[componentCount++] = comp;
}
2) components[0]->Display() will work, if display is a member function of GameComponent class.

Overload constructors for a class structure with more than one instance of that class structure

Hello to all that read
I am self learning C++ from a text book.
...and I have been given a serious of questions that I am have trouble interpreting, the questions are:
4.
Modify the constructor of Exercise 3 so that it assigns a new ID number as each variable is established. The ID number should be output to the screen.
**Please Note: Exercise 3 was just adding a Class constructor to the class structure - and basically setting all the class private member variables to '0' within that added constructor.
5.
Add constructors to the class of exercise 4. They should output the ID number when they are invoked.
6.
Write a constructor whose argument is an ID number. Overload it with the constructor of(Exercise 5) and then Write a main program to test this new constructor.
**So the questions: 4 and 5 are confusing me as they appear to be asking the same questions (i.e outputting the I.D numbers) and I need more than one 'constructor' in order to do this( I get that part).
**Question 6 Is effectively asking me to overload more than one instance declared of the class with an ID number as the argument!!!! I am confused because in my text book it specifically states that you cannot have an argument for a constructor when you have an array of classes declared within in the main program.
So if anyone can shed light on these questions and clarify how they would proceed I would appreciate the help. I appreciate that I may of interpreted the questions wrongly that is why I am asking for help.
**Please note: The name of the class: 'class classroom' is not ideal but it is what I copied from the text book question!
**Please also note that I have answered (I think!) exercise/question 4 by adding code that Id's each instance of the class variable.
And the relevant code relating to the above questions are:
#include <iostream>
#include <cstdio>
using namespace std;
class classroom{
char name[25];
int student_id;
float grades[10];
float average;
int num_tests;
float letter_grade;
**static int next_student_id;**
public:
void enter_name_id(void);
void enter_grade(void);
void average_grades(void);
void letter_grades(void);
void output_name_id_grade(void);
classroom();
};
**int classroom::next_student_id=1;**
and the constructor:
classroom::classroom(){
int i;
num_tests=0;
**student_id=next_student_id++;**
**cout<<"\nstudent id: "<<student_id;**
average=0.0;
for(i=0;i<10;i++){
grades[i]=0.0;
}
for(i=0;i<27;i++){
name[i]='-';
}
cout<<"\n*****************Finished*****************";
}
And the main program declaration:
int main()
{
classroom students[3];
//and so on...
}
and the code added for question/Exercise 4 was:
in the class structure I added the following private member variable:
**static int next_student_id;**
and outside of the class structure I initialized the static variable to 1
int classroom::next_student_id=1;
and in the constructor I added this code: which basically outputted to the screen a unique ID for each instance of classroom class variable:
student_id=next_student_id++;
** cout<<"\nstudent id: "<
Many thanks in advance
Questions 4 and 5 do appear to be the same from what you've provided - I'd reread it carefully to be sure, but it wouldn't be the first time textbook examples had a typo (in fact, I've run across that many times - alot of book companies are lazy when it comes to the exercises).
You do have the right answer with your static counter, so I wouldn't worry about it - you've understood the goal and solved the problem.
Question 6... it sounds like it wants you to just add an extra constructor to the class - so, you would have the default constructor (which you must explicitly write, but you already have done this in order to do your static counter), and you would also have a one-parameter constructor taking an integer. The one-parameter constructor should not need to use the static variable as it is allowing the user to provide the id to the class explicitly.
Moving on (since I think you've already got all of this), you are also correct in thinking that you can't provide an argument to a constructor when making an array. To test #6 as it suggests, you'll either have to make a stand-alone object (i.e. not an array), or something like a std::vector or other container that provides this capability.
#include <iostream>
#include <vector>
class A {
public:
A(int i) { /* Empty */ }
};
int main()
{
//Creates a new vector holding 5 A's initialized with the 2nd parameter.
std::vector<A> myVec(5, A(7));
}
Note that this technically creates a temporary A which is used to initialize the 5 vector entries. Also note that a std::vector is part of the STL (standard library), and it is basically a dynamically sized array.
Where, point 6, requires to have an array of class objects?
int main()
{
classroom studentA(100);
classroom studentB();
classroom studentC(200);
classroom studentD();
classroom students[100];
//and so on...
}