Accessing multilayered structs results in error - c++

I'm working on a homework assignment that involves creating structures for vending machines around campus. I'm getting the error "'vendingMachines' was not declared in this scope" and I can't figure out the solution. Would I have to run a for loop in main to declare the vendingmachines struct?
struct Location
{
std::string buildingName;
int floorLevel;
};
struct Drink
{
std::string drinkName;
float drinkSize;
float drinkPrice;
};
struct VendingMachine
{
Location machineLocation;
Drink drinkTypes[10];
};
struct AllVendingMachines
{
VendingMachine vendingMachines[5];
};
int checkPurchase(std::string buildingName, int floorLevel, std::string drinkName, f$
{
bool correct = true;
for (int i = 0; i < 5; i++)
{
if (vendingMachines[i].machineLocation.buildingName != buildingName)
{
correct = false;
}
if (vendingMachines[i].machineLocation.floorLevel != floorLevel)
{
correct = false;
}
for (int c = 0; c < 10; c++)
{
if (vendingMachines[i].drinkTypes[c].drinkName != drinkName)
{
correct = false;
}
if (vendingMachines[i].drinkTypes[c].drinkSize != drinkSize)
{
correct = false;
}
}
}
if (correct == true)
{
return 1;
}
else
{
return 0;
}
}

You're attempting to access vendingMachines in checkPurchase().
However, that's a member of the struct AllVendingMachines. Which means each AllVendingMachines object will have a vendingMachines array. So whose vendingMachines are you trying to access?
The simplest solution I can see would be to take an AllVendingMachines object as a function argument:
int checkPurchase(std::string buildingName, int floorLevel, std::string drinkName, AllVendingMachines machines)
{
bool correct = true;
for (int i = 0; i < 5; i++)
{
if (machines.vendingMachines[i].machineLocation.buildingName != buildingName)
{
correct = false;
}
// ...

You have declared vendingMachines to be part of struct AllVendingMachines, but you have never created an instance of that struct. Therefore, not a single instance of the member array 'vendingMachines' exists.
You could simply make the array vendingMachines a global variable, i.e. move it out of struct AllVendingMachines, or you could create a global instance of struct AllVendingMachines, by changing the declaration to the following:
struct AllVendingMachines
{
VendingMachine vendingMachines[5];
} all_vending_machines_global_instance;
In the latter case, you must change all references to vendingMachines[i] in the function checkPurchase to all_vending_machines_global_instance.vendingMachines[i].
I don't want to encourage the use of long variable names, I just gave it this long name for clarity.
Alternatively, if you don't want to use global variables, you can make the function checkPurchase receive an additional paramater consisting of a pointer or reference to an instance of struct AllVendingMachines or directly to an instance of the vendingMachines member array.

Related

Access an undeclared struct?

I there a way to access a struct that has not been declared yet?
//Need to some how declare 'monitor' up here, with out moving 'monitor' above 'device'
//because both structs need to be able to access each others members
struct{
int ID = 10;
int Get__Monitor__ID(){
return monitor.ID; //obvioulsly 'monitor' is not declared yet, therefore throws error and is not accessible
}
} device;
struct{
int ID = 6;
int Get__Device__ID(){
return device.ID; //because 'device' is declared above this struct, the ID member is accessible
}
} monitor;
In this particular case, you can define the function prototype in the struct, and the definition can come later.
struct device_t {
int ID = 10;
int Get__Monitor__ID();
} device;
struct monitor_t {
int ID = 6;
int Get__Device__ID();
} monitor;
int device_t::Get__Monitor__ID() {
return monitor.ID;
}
int monitor_t::Get__Device__ID() {
return device.ID;
}

Correctly set return of a function between base and derived class

I have a problem with the following task. I have two classes Config(base) and Ising(derived) each of which has a std::array of 12 bool. I created a function Incr() which does the following
-if the i-th elem of the array is false Incr() sets it as true and exit;
-if the i-th elem of the array is true sets it as false and then moves to the i+1-th elem.
Incr() must work if I call it twice (as in foo.Incr().Incr()) so I thought it should return a reference to a Config
I am now required (it is an exercise )to create an std::vector of 4096 Ising object all created via application of Incr() to the preceding Ising object. Fact is that this function returns a Config...
I can set it to return a Ising but this seems a very poor design choice to have a base class method which returns an object of its derived class.
I was wondering whether there is a more elegant way to do this
This is what I am working with:
class Config {
public:
//ctor
Config(){
for(auto i=m_arr.begin(); i !=m_arr.end(); i++){
*i = false;
}
};
//incr function
Config& Incr(){
for(auto i = m_arr.begin(); i != m_arr.end(); i++){
if(*i ==false){*i = true; return *this;}
else{
*i=false;
}
}
return *this;
};
private:
std::array<bool,12> m_arr;
};
class Ising: public Config{
public:
Ising(double g =1): m_g(g){
};
private:
double m_g;
};
int main(){
Config f; //check ctor
Ising is(3);
is.Incr();
std::vector<Ising> vec;
vec.push_back(is);
for(int i=0; i < 4096; i++){
vec.push_back(vec[i].Incr());
}
return 0;
}
Thanks to everyone who will help
What's wrong with this? No need for a redesign.
Ising is(3);
is.Incr();
std::vector<Ising> vec;
vec.push_back(is);
for (int i = 0; i < 4096; i++) {
vec[i].Incr();
vec.push_back(vec[i]);
}

c ++ Class Method Pointer as Function Argument

I am trying to create a dynamic function pointer that points to some methods all the methods I want to save on the array return a bool and have an uint32_t parameter. The functions are Service functions. These are intended to be dynamic, so when a class is started, the constructor links the service function from the object to be called from outside the object.
With the code below I am getting the following error:
Build error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.
I have no clue what to do to overcome this problem, any idea would be greatly appreciated, thanks!
//File 1
typedef bool (*ServiceFunctionsType)(uint32_t);
//File 2
#include "File1.hpp"
extern uint8_t ServiceFunctions_size;
extern ServiceFunctionsType *ServiceFunctions;
void Service_Functions_Setup();
bool SetPtr(ServiceFunctionsType a);
void ClearPtr(uint8_t id);
//File 3
#include "File1.hpp"
ServiceFunctionsType *ServiceFunctions;
uint8_t ServiceFunctions_size = 0;
//File 4
#include "File2.hpp"
#include <stdlib.h>
void Service_Functions_Setup()
{
ServiceFunctions = NULL;
if(SERVICE_FUNCTION_POINTER_START_SIZE != 0)
{
ServiceFunctions_size = SERVICE_FUNCTION_POINTER_START_SIZE;
ServiceFunctions = (ServiceFunctionsType*)malloc(sizeof(ServiceFunctionsType)*SERVICE_FUNCTION_POINTER_START_SIZE);
for(uint8_t i = 0; i < SERVICE_FUNCTION_POINTER_START_SIZE; i++)
{
ServiceFunctions[i] = NULL;
}
}
}
uint8_t SetServiceFunctionPointer(ServiceFunctionsType a, bool _realloc)
{
if( ServiceFunctions == NULL )
{
ServiceFunctions = (ServiceFunctionsType*)malloc(sizeof(ServiceFunctionsType));
ServiceFunctions[0] = a;
return 0;
}
for(uint8_t i = 0; i < ServiceFunctions_size; i++)
{
if( ServiceFunctions[i] == NULL )
{
ServiceFunctions[i] = a;
return i;
}
}
if(_realloc)
{
ServiceFunctions_size++;
ServiceFunctions = (ServiceFunctionsType*)realloc(ServiceFunctions,sizeof(ServiceFunctionsType)*ServiceFunctions_size);
ServiceFunctions[ServiceFunctions_size - 1] = a;
return ServiceFunctions_size - 1;
}
return INVALID_SERVICE_FUNCTION_POINTER;
}
void ClearServiceFunctionPointer(uint8_t id)
{
ServiceFunctions[id] = NULL;
}
//File 5
class MonoStepSequencer
{
public:
MonoStepSequencer();
~MonoStepSequencer();
uint8_t ServicePointerID;
bool Service(uint32_t time);
private:
};
//File 6
#include "File2.hpp"
MonoStepSequencer::MonoStepSequencer()
{
ServicePointerID = SetServiceFunctionPointer(&this -> Service);
}
//This is the function to be called with a pointer
bool MonoStepSequencer::Service(uint32_t time)
{
//Some Code
}
You can try, to use lambdas. Create method like
std::function<void()> getService()
Where inside you can use:
return [this](){
Service();
};
Also if your methods should use arguments, you can use this method, but add arguments into return value and lambda.
One more, you can create lambda outside of class methods, like:
[&object]()
{
object.Service();
}
In this way, better to use std::shared_ptr to guаrantee that object exists, when lambda called.
this -> Service is an unqualified or parenthesized non-static member function
You probably meant :: instead of -> Also, you need a type on the left, not a variable.
Also, please don't put spaces around ->. That makes it look like you're specifying a trailing return type or something.

how to declare variables based on other params in C++

I have the below code (eg):
void Foo(int ip_selector)
{
ipv4_hdr_t ipv4;
ipv6_hdr_t ipv6;
{
…
if(ip_selector == 0)
addStack(ipv4);
else
addStack(ipv6);
}
{
…
if(ip_selector == 0)
addStack(ipv4);
else
addStack(ipv6);
}
…
}
int main()
{
for (int i = 0; i < 2; i++) {
Foo(i);
}
}
In the above code, addStack param depends on the selector param in Foo(). The above code works fine, but does to the scale it can grow, I do not want to add if ip_selector check everywhere in Foo() to see which arg to be passed in addStack(). I am trying to find a way to select either ipv4_hdr_t/ipv6_hdr_t without writing an if else condition. Infact, I dont even need the ipv6 declaration of ip_selector is 0 (vice versa for that matter)
here is one way to solve such a problem.
1.have a base class for your protocols, say Protocol.
2.derive your ip4/ip6/whateverelse classes from the base class.
3.create an array of available protocols.
4.use the selector to pick an array element.
class Protocol {
virtual void addStack() = 0;
...
};
class Ip4Protocol : public Protocol {
ip4_hdr_type hdr;
void addStack(){...}
};
vector<Protocol*> availableProtocols = {
new Ip4Protocol(),
new IP6Protocol(),
...
};
...
for (int i = 0; i < availableProtocols.size(); i++) {
avalableProtocols[i]->addStack();
}
or you can probably use templates on the derived classes as well
termplate <class P> class IP : public Protocol {
P hdr;
void addStack() {addGlobalStack(hdr)};
}
ther are tons of other possibilities as well.

C++: how to get element defined in a different function of same class?

I defined a class in the header file like this:
class myClass
{
public:
void test();
void train();
private:
bool check;
}
Then in the cpp file, I did this:
void myClass::test()
{
int count = 9;
//some other work
}
void myClass::train()
{
int newValue = count;
....
}
Then without surprise, I got an error saying count is not defined. So what I want to do is in my train function use the count value that is defined in the test. Is there any good way to do this without using any additional dependencies? Thank you.
Well yes. That's called a member variable. Exactly like your bool check;.
Do
private:
bool check;
int count;
and then use it directly in your functions.
void myClass::test()
{
count = 9;
//Same as this->count = 9;
}
void myClass::train()
{
int newValue = count;
//Same as int newValue = this->count;
}
In your example, when method test finishes its work, count variable does not exist anymore, so there's no way of accessing it. You have to ensure, that its lifetime will be long enough to be accessed from another place. Making it a class field solves the problem (this is what class fields are for :)).
Do it this way:
class myClass
{
public:
void test();
void train();
private:
bool check;
int count; // <- here
}
and then
void myClass::test()
{
count = 9;
//some other work
}
But that's not the only solution. You can do it in another way, say:
class myClass
{
public:
int test()
{
// do some work
return 9;
}
void train(int count)
{
int newValue = count;
}
}
// (somewhere)
myClass c;
int count = c.test();
c.train(count);
That all depends on what test, train and count are for...