Cannot assign element std::array directly, it says no operator "=" matches - c++

In my processor class there is an array <Job, 10>.
void Processor::addJob(Job job) {
this->Jobs[this->uBound] = job;
this->uBound++;
}
I'd like to add a new element inside my processor class. to do that i create new private: int uBound = 0 property in my processor class. and I assign directly this->Jobs[this->uBound] = job;. it gives me an error. it says Error : no operator "=" matches these operands. operand types are: std::array<Job, 10U> = Job.
so I tried to use this->Job->assign(Job); it assigned to all elements of my Jobs, but I just wanted only one element.
here the class of Job
class Job {
public:
string name;
public :
int length = 0;
public:
bool used = false;
public:
Job();
public:
Job(string n, int l);
~Job();
};
and here the Processor class
class Processor {
private:
int turnArround_time = 0;
private:
int uBound = 0;
public:
std::array<Job, 10> *Jobs = new std::array<Job, 10>();
public:
Processor();
public:
void addJob(Job job);
public:
int getTurnArround();
~Processor();
};
I have no idea what does the error mean.
Is there any alternative way to add Job object to Processor->Jobs ?
any help appreciated, thanks...

The correct syntax will look like
( *this->Jobs )[this->uBound] = job;
Though it is not clear why the array is allocated dynamically.
Of course you also could write for example :)
this->Jobs[0][this->uBound] = job;
but it only confuses the reader of the code.

Related

call C++ member function from the string input format

suppose i have a simple C++ class :
class Calc
{
private:
int a;
public:
Calc(){
a = 0;
}
void seta(int a){
this->a = a;
}
int geta(){
return a;
}
};
Now, suppose, in main i create a object of this class, and take two inputs from user : var_name which is name of instance variable in string format, and action which is set or get in string format. For ex : if var_name = "a" and action == "get" , then i should be able to call geta() fn. Is there any way to achieve this in C++.
pls dont provide if..then..else kind of soln. I want to write a generic code which need not be updated as more members are added in class Calc.
You cannot dynamically modify C++ types. However, it sounds like you just want a way to set and read attributes. You don't need to modify your class structure for this, there are other alternative solutions. For example you could use an std::map:
class Calc
{
private:
std::map<std::string, int> attributes;
public:
Calc(){}
void setAttr(const std::string& name, int value){
attributes[name] = value;
}
int getAttr(const std::string& name){
return attributes[name];
}
};

C++ Invalid conversion from interface class to child class

I am trying to solve this problem but I don't know how to make conversion from interface class to my child class. Basicly, I am trying to make array of Vehicle pointers and elements of array to be child classes pointers, then pass element by element to Counter class method which will calculate value of total passengers, but I get compiler error:
invalid conversion from 'oss:Vehicle*' to 'oss::Bike*' [-fPermissive]
Here is my code:
Vehicle.h
using namespace std;
namespace oss{
class Vehicle
{
public:
virtual string type() = 0;
virtual unsigned passengers() = 0;
virtual ~Vehicle();
};
class Land_vehicle : public Vehicle{
protected:
string typeOfVehicle;
unsigned numberOfPassengers;
public:
Land_vehicle();
string type();
};
class Bike : public Land_vehicle{
public:
Bike();
unsigned passengers();
};
class Counter{
private:
int totalPassengers;
public:
Counter();
void add(Bike*b);
int total();
};
Vehicle.cpp
using namespace oss;
Vehicle::~Vehicle(){};
Land_vehicle::Land_vehicle(){typeOfVehicle = "Land";}
string Land_vehicle::type(){return typeOfVehicle;}
Bike::Bike(){numberOfPassengers = 1;}
unsigned Bike::passengers(){return numberOfPassengers;}
Counter::Counter(){totalPassengers = 0;}
void Counter::add(Bike b){
cout <<"inside add bike"<<endl;
totalPassengers += b.passengers();
}
int Counter::total(){return totalPassengers;}
Main.cpp
using namespace std;
using namespace oss;
int main()
{
Counter c;
Vehicle* v[] = {new Bike};
size_t sz = sizeof v/sizeof v[0];
for (unsigned i = 0; i < sz; ++i)
c.add(v[i]);
std::cout << "Total: " << c.total() << " passengers!" << std::endl;
for (unsigned i = 0; i < sz; ++i)
delete v[i];
return 0;
}
According to your classes, every Bike and every Car are Vehicules. THis is why, whenever you need a Vehicle*, you can use as well a Bike*or aCar*`.
You make use of this in your assignment:
Vehicle* v[] = {new Bike}; // yes a Bike* can be converted to a Vehicle*
However the reverse relation is not true. Not every Vehicle is necessary a Bike. This is why you can't just use a Vehicle* when you need a Bike*. To do the reverse condition you first have to check that the Vehicle you're working with is indeed a Bike, and if it's the case you can use casting.
Fortunately, your classes are polymorphic (due to the virtual functions). So you have to use a dynamic_cast() to convert from parent (base) pointer to child (derived) pointer. But take care to check that the conversion succeeds (i.e. casted pointer isn't null).
What's wrong here ?
You experience this and related problems, when you try to add a vehicle to your counter:
c.add(v[i]); // v[i] is a pointer to a vehicle, but which one
In fact there are several problems with your Counter::add() :
first, you have a plain object as argument, not a pointer. This means that you'd need to dereference the pointer with c.add(*v[i]). But the overload require that you tell at compile time which type of object it is (i.e. there's no add(Vehicle), and if there would be one, you'd suffer from object slicing)
then, if you'd use a pointer instead of a plain object, you could use casting: c.add(dynamic_cast<Bike*>(v[i]);
finally, you'll realize that even with casting, you have a problem: in your example you vow that there's only a bike in your array. But in real code, you couldn't now for sure.
First work around
Now putting this together, here is how to modify your loop to add to the counter only bikes:
for (unsigned i = 0; i < sz; ++i) {
if (dynamic_cast<Bike*>(v[i]))
c.add(dynamic_cast<Bike*>(v[i]));
}
THis suppose to change the signature of add to:
void Counter::add(Bike* b){
cout <<"inside add bike"<<endl;
totalPassengers += b->passengers();
}
Here a live demo
And a solution
If you have polymorphic classes, it's a pitty not to benefit from polymorphism:
class Counter {
int totalPassengers;
public:
Counter();
void add(Vehicle* b);
int total();
};
And the implementation of the redesigned function:
void Counter::add(Vehicle* b){
totalPassengers += b->passengers();
}
And this will work whatever the number of classes you derive from vehicle ! No longer need to add dozens of similar overloads of the same function.
Online demo

Initializing object to an empty list from a reference parameter

class ListOfGifts
{
private:
Gift list[50];
int count = 0;
public:
void suggest(ListOfGifts& affordable, float dollarLimit) const
{
// how do I initialize affordable to an empty list without a constructor
}
}
Trying to initialize a list from a parameter that is a reference. How can I do this?
Use an std::array:
class ListOfGifts
{
private:
std::array<Gift, 50> list;
int count = 0;
public:
void suggest(ListOfGifts& affordable, float dollarLimit) const
{
affordable.list = std::array<Gift, 50>{};
}
}
FYI, C++ is literally built on constructors. They will come up eventually, and they're actually quite helpful.

No match for operator '='

Hi I'm a beginner C++ developer..I have a problem with a code that I post so it's easier to understand the problem.
Obj.h
class Obj : public QObject
{
Q_OBJECT
public:
typedef void (*factionState)();
struct Tran {
factionState Action;
unsigned int nextState;
};
void processAction(myState)
{
Tran const*t = myarrayAction + myState
*(t->action)();
myState=t->nextState;
}
private:
Tran const *myarrayAction;
unsigned int numStates;
protected:
myObj;
myState;
public:
Obj (Tran *arrayAction, const int nStates, const int i) {arrayAction=myarrayAction, numStates = nStates;};
void doNothing(){printf ("Do NOthing called\n")};
Obj_1.h
#include "Obj.h"
const int Obj_1=1
class Obj_1 : public Obj
{
private:
typedef enum {
OffState,
InitState,
RunState,
}state ;
static Obj::Tran myarrayAction[3];
public:
Obj_1() : Obj(myarrayAction, 3, Obj_1) {myState=OffState, myObj=Obj_1,init();};
private:
void init();
void GoToInitState();
void GoToRunState();
};
Obj_1.cpp
void Obj_1::init()
{
myarrayAction[3] = {
{&Obj::doNothing, OffState},
{&Obj_1::GoToInitState, InitState},
{&Obj_1::GoToRunState, RunState},
};
}
void Obj_1::GoToInitState()
{
// code;
}
void Obj_1::GoToRunState()
{
// code;
}
When I build the code I have this error:
no match for 'operator=' (operand types are 'Obj::Tran' and ''). So I tried to remove '=' and write Obj1::init like this
myarrayAction[3] {
{&Obj::doNothing, OffState},
{&Obj_1::GoToInitState, InitState},
{&Obj_1::GoToRunState, RunState},
};
But I have a sintax error..Any ideas??
Thanks
A couple of things. First, when Obj_1::init() executes, myarrayAction has already been initialized by the constructor. The { } syntax, which works for some array initializations, is not going to work here. You need an object (not a list of initializers) on the right-hand side of =.
Second, it looks like you want Obj_1::init() to set the contents of all three of the Obj::Tran objects within myarrayAction. But when you start a statement like this, myarrayAction[3] =, it is going to try to set the array member myarrayAction[3], that is, the fourth member of the array myarrayAction (whose first three members are myarrayAction[0], myarrayAction[1], myarrayAction[2]). But this array has only three members.
You are better off to write something like this:
myarrayAction[0] = ... ;
myarrayAction[1] = ... ;
myarrayAction[2] = ... ;
In the ... parts you call the constructors of the three objects you want to store at those three locations, passing the values you want to the parameters of each of these constructors.
Another thing you could do is, instead of using Obj::Tran* to represent an array of Obj::Tran, actually use a class to implement this array. If you know STL you could write std::vector<Obj::Tran>, for example. Or you could write your own class, depending on what you want. If you write a class, you can also write a constructor that takes the list of values you want as parameters, though you will not be able to organize them into sublists with nested { } as you could with an array initializer list.

Initialization of array-of-classes member of a class

I want to initialize array-of-classes member of a class
const int count = 5;
class In
{
float rate;
public:
In( int index )
{
rate = index / count;
}
};
class Out
{
In ins[count];
public:
Out() : /* ??? */
{
}
};
Can I obtain index of instance of In in initialization ins if I will rely on initialization list of Out::Out()
You can't do that. You need to define a default constructor for In.
Or better yet, use a std::vector.
EDIT: Might be supported in C++11, not sure though.