For the following class I wanted to make a vector with 10 Ship() objects
However this yields the following compilation error invalid conversion from 'int' to 'const char*' [-fpermissive]
( If I omit the vector line it compiles just fine)
I did a little search and could not find an answer.
class Ship
{
protected:
std::string name;
public:
Ship(std::string name="Ship")
{
std::ostringstream tmp;
std::string temp;
tmp << name << ++id;
name = tmp.str();
}
};
Vector Declaration in main()
#include <iostream>
#include <vector>
#include <string>
#include "Ship.h"
using std::cout;
using std::endl;
using std::vector;
int main()
{
vector<Ship> Shipyard; //10% of map dimension is number of ships
Shipyard.push_back(Ship(10)); //push_back(Ship(),10); doesn't work also
}
The constructor takes a std::string, but you're passing an integer
For 10 objects construction of same name use this 2nd form of constructor of std::vector :
vector<Ship> Shipyard( 10, Ship() );
Ship(10)
This will try to create one Ship object and call the constructor. However your constructor take string as argument and hence the error.
To create vector of 10 Ships use:
vector<Ship> Shipyard(10, Ship());
You are constructing a Ship object with the value of 10. Since the constructor takes std::string, you cannot pass an integer to the constructor.
To add 10 ships:
std::vector<Ship> ShipYard(10);
or
std::vector<Ship> ShipYard;
ShipYard.resize(10);
Related
I am having trouble compiling the following:
#include <QVector>
#include <QDebug>
#include <vector>
class item
{
int var;
public:
//Without default constructor this program will not compile
//item(){}
item(int value)
{
var = value;
}
int getVar()
{
return var;
}
};
int main()
{
//This code will not compile
QVector<item> y;
y.append(item(1));
qDebug() << y[0].getVar();
//std::vector however will work despite an absence of a default contructor
std::vector<item> z;
z.push_back(item(1));
qDebug() << z.at(0).getVar();
return 0;
}
To be precise the append line will not compile.
Why item has to have a default contructor in this case?
The reason why std::vector works differently lies in the fact that in vector, raw uninitialized memory is allocated and then calls copy constructor to do the copy whenever required. This process doesn't require calling default constructor for resize(). That's why there is no dependency as such on default constructor.
For more info, See AnT's answer here.
QVector requires type to be default constructible because of the way the internal function realloc() is implemented.
Source: Understanding the Qt containers
I am having a problem with assigning new values to a dynamic int array that is a data member variable of the class IntersectionFlowRate(). I can initialize and print the values of the array inside the constructor. However, when I exit the constructor to the another class and then later call a function within the IntersectionFlowRate() class passing in variables to overwrite the initial values of the data member it will segmentation fault. I have debugged to find that overwriting the array is causing the seg fault. And that even attempting to access the dynamic array within one of its functions will seg fault.
My question is how can I edit the values of a dynamic int array member variable from within one of its functions i.e setArrayElement(int index, int x).
Here is some of my code. Sorry if I am unclear or missing something ridiculous. I have been stuck on this for hours.
#ifndef INTERSECTIONFLOWRATE_H
#define INTERSECTIONFLOWRATE_H
class IntersectionFlowRate
{
public:
IntersectionFlowRate();
~IntersectionFlowRate();
void setFlowCycle(int index, int flow);
private:
int* m_flowRateMotorCycle;
};
#endif
in the .h file ^
#include "IntersectionFlowRate.h"
#include <cstdlib>
#include <iostream>
#include <new>
using namespace std;
IntersectionFlowRate::IntersectionFlowRate()
{
const int SIZE = 4; //Constant for m_flowRates[] size
//DYNAMIC MEMORY DELETE LATER
m_flowRateMotorCycle = new int[SIZE];
for(int i = 0; i < SIZE; i++){
m_flowRateMotorCycle[i] = 0;
cout << m_flowRateMotorCycle[i] << endl;
cout << "WE GOT HERE" << endl;
}
}
void IntersectionFlowRate::setFlowCycle(int index, int flow){
cout << "INDEX: " << index << endl;
cout << "FLOW: " << flow << endl;
m_flowRateMotorCycle[index] = flow; //seg fault is here
}
I have another class that creates a pointer to a IntersectionFlowRate() object and then calls its setFlowCycle function passing in two VALID ints. With the debugging I was able pass 0 and 3 to the function setFlowCycle(0, 3) just fine and output those variables within the function.
#ifndef TRAFFICSIM_H
#define TRAFFICSIM_H
#include "IntersectionFlowRate.h"
using namespace std;
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
~TrafficSim(); //Destructor
private:
IntersectionFlowRate* m_flowRate;
};
#endif
#include "TrafficSim.h"
#include "IntersectionFlowRate.h"
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
I replicated the error with this code. If no one else can I am completely unsure of what is possibly wrong anymore.
You are setting a local variable called m_flowRate, not the member variable m_flowRate of your TrafficSim class:
Instead of this:
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
It should be this:
TrafficSim::TrafficSim()
{
m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
But overall, it not need be a pointer. It could be an object member within your class. That would cut down on the pointer usage a bit:
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
private:
IntersectionFlowRate m_flowRate;
};
Then:
TrafficSim::TrafficSim()
{
m_flowRate.setFlowCycle(0, 3);
}
As to your question as to how to incorporate usage of std::vector in your class, here is a code sample of the IntersectionFlowRate class, rewritten using vector:
Vector sample
Also, another source of problems is that your classes fail to follow the Rule of 3 when you have pointers to dynamically allocated memory in your class.
Using std::vector takes care of this automatically, but if you insist on using pointers, you need to adhere to the directions at the link posted.
Yes, use a std::vector, it is much simpler, and it is a template so it also pretty fast and works any type (best for primitive types or pointers to objects) , and it also has boundary checking and other useful things.
If you need fast array-like access then you could use std::map which associates a key with a value, like so
std::map<UINT, YourClass*> m_mapIDs_to_YourClass;
When you first start using stl containers they might seem a little strange, but after a short while you cannot do without them, luckily they have been part of the C++ standard for some time now.
Boundary check for both these containers can be done by comparing your iterator to mapYourMap.end(), if they are equal you have passed the last element and trying to access data through the iterator will cause an exception.
Example for std::vector (if vecInt is a vector< int >):
vector<int>::iterator it = vecInt.begind();
if (it == vecInt.end()) return; // vector is empty
do { // runs through elememts until out of bound, useful for searching
i++
while (it != vecInt.end());
I am just wondering how I could solve this problem.
I have a
vector<char> vstr;
definition in the class Program.
Then in the class constructor I want to init this vector with an array:
char arrayOfChars[] = {'a', 'b', 'c'};
this.vstr = new vector<string>(arrayOfChars, arrayOfChars + sizeof(arrayOfChars)/sizeof(arrayOfChar[0]));
The build gives me a bug:
error: request for member 'vstr' int 'this', which is of non-class type 'Program *const' .
Could you give me a simple solution for this error?
I'm not an expert in C++ but I see at least two problems:
You are trying to initialise an object with a pointer. Don't use new key word.
What is more this pointer points to vector of strings not chars, so replace vector<string> with vector<char>.
As melak47 says in his comment this.vstr is also incorrect because this is a pointer and therefore should be replaced with this->vstr or simply vstr
Once you make all the three corrections it should compile
I think that piece of code is what you want.
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
class Program {
vector<char> vstr;
public:
Program(const char* data)
{
string s(data);
std::copy(s.begin(), s.end(), std::back_inserter(vstr));
}
void PrintData()
{
for (auto it = vstr.begin(); it != vstr.end(); it++)
{
std::cout << (*it);
}
}
};
int main()
{
Program p("simple data");
p.PrintData();
}
Fairly simple question here, whats the best way to fill a vector outside of a function in a class .cpp file? currently i'm attempting the following which is not working:
std::vector<Player> midfielder(8);
midfielder.at(0) = Midfielder("Default ",0,"Midfielder");
midfielder.at(1) = Midfielder("David Armitage ",1,"Midfielder");
midfielder.at(2) = Midfielder("Tom Rockliff ",2,"Midfielder");
midfielder.at(3) = Midfielder("Gary Ablett ",3,"Midfielder");
midfielder.at(4) = Midfielder("Dyson Heppel ",4,"Midfielder");
midfielder.at(5) = Midfielder("Scott Pendlebury",5,"Midfielder");
midfielder.at(6) = Midfielder("Michael Barlow ",6,"Midfielder");
midfielder.at(7) = Midfielder("Jack Steven ",7,"Midfielder");
To provide context, 'Midfielder' is a class that inherits from the 'Player' class.
TeamManagment.h
#ifndef TEAMMANAGEMENT_H
#define TEAMMANAGEMENT_H
#include <vector>
#include "Player.h"
#include "Midfielder.h"
#include <string>
class TeamManagement
{
public:
TeamManagement();
void Display_Players();
};
#endif // TEAMMANAGEMENT_H
TeamManagement.cpp
#include <iostream>
#include <string>
#include <vector>
#include "Player.h"
#include "Midfielder.h"
#include "TeamManagement.h"
using namespace std;
TeamManagement::TeamManagement()
{
}
std::vector<Player> midfielder(8);
//errors start occurring on line below: 'midfielder' does not name a type
midfielder.at(0) = Midfielder("Default ",0,"Midfielder");
midfielder.at(1) = Midfielder("David Armitage ",1,"Midfielder");
midfielder.at(2) = Midfielder("Tom Rockliff ",2,"Midfielder");
midfielder.at(3) = Midfielder("Gary Ablett ",3,"Midfielder");
midfielder.at(4) = Midfielder("Dyson Heppel ",4,"Midfielder");
midfielder.at(5) = Midfielder("Scott Pendlebury",5,"Midfielder");
midfielder.at(6) = Midfielder("Michael Barlow ",6,"Midfielder");
midfielder.at(7) = Midfielder("Jack Steven ",7,"Midfielder");
//errors stop occurring here
void TeamManagement::Display_Players(){
cout<<"Position Name ID"<<endl;
for (int i=1;i<8;i++)
{
cout<<midfielder[i].Player_Details()<<" "<<midfielder[i].Get_player_id()<<endl;
}
}
The first problem is that you cannot perform assignment like that outside of a function. You must use construction or initialization.
With C++98 you cannot populate/initialize a vector outside of a function.
With C++11/14 you can populate one using initializer syntax:
#include <iostream>
#include <vector>
struct Thing {
int m_i, m_j;
Thing(int i, int j) : m_i(i), m_j(j) {}
};
std::vector<Thing> things {
{ 1, 2 }, { 2, 3 }
};
int main() {
std::cout << "things[0].m_j = " << things[0].m_j << '\n';
}
But std::vector won't like you trying to put "Midfielder"s into a vector of Player. Lets use an SSCCE to reconstruct the damage you're doing:
#include <iostream>
struct Base {
int i;
};
struct Derived : public Base {
int j;
};
int main() {
std::cout << "Base size = " << sizeof(Base) << '\n';
std::cout << "Derived size = " << sizeof(Derived) << '\n';
}
This tells us that Base and Derived have a different size. But you're trying to put these two objects into the same container because they're related. Round peg and square peg are related... They won't fit into the same hole, and this is the problem we have now.
The vector creates space in memory for your elements based on the type you supply, and then it requires you to pass it exactly that type to populate those spaces with, or a type that has a conversion mechanism to the storage type.
If you want to have a container of different types, you'll need to use pointers, but then you're going to run into the problem that what you get back will be a pointer to the base type and you will need to provide yourself with a way to distinguish different player types.
See Store derived class objects in base class variables for the C++98 approach. In modern C++ (11 and 14) you should use smart pointers, e.g.
std::vector<std::unique_ptr<Base>>
std::vector<std::shared_ptr<Base>>
Presumably default constructing a Midfielder doesn't make a lot of sense, so you can reserve the memory, then emplace_back into the vector.
std::vector<Player> midfielder {};
midfielder.reserve(8);
midfielder.emplace_back("Default ",0,"Midfielder");
midfielder.emplace_back("David Armitage ",1,"Midfielder");
midfielder.emplace_back("Tom Rockliff ",2,"Midfielder");
midfielder.emplace_back("Gary Ablett ",3,"Midfielder");
midfielder.emplace_back("Dyson Heppel ",4,"Midfielder");
midfielder.emplace_back("Scott Pendlebury",5,"Midfielder");
midfielder.emplace_back("Michael Barlow ",6,"Midfielder");
midfielder.emplace_back("Jack Steven ",7,"Midfielder");
midfielder.at(0) = Midfielder("Default ",0,"Midfielder"); is a statement. You've put that and similar statements in (global) namespace scope. That's your bug. Only declarations may be in namespace scope. You must put your statements inside a function.
The error message stems from the fact that declarations which don't start with a keyword start with a type name. Since midfielder is not a keyword, the compiler expects it to be a type name but it isn't one, so you get the error.
I've started to build up a little data type and at the current stage I have only one recursive type in a boost variant. It turns out, I get a segfault when I try to instantiate my type. If I put a string before the recursive type it works, putting it after the type it doesn't. I'm using mingw with gcc 4.8.1 64bit and boost 1.54.
Am I using boost variant the wrong way?
#include <boost/variant.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <string>
#include <iostream>
struct A;
struct B;
using C = boost::variant<boost::recursive_wrapper<A>>;
// works:
// using C = boost::variant<std::string, boost::recursive_wrapper<A>>;
struct A {
std::string name;
C variant;
};
struct B {
std::string name;
C variant;
};
int main() {
std::cout << "start" << std::endl;
B hAST; // <--- segfaults
std::cout << "end" << std::endl;
return 0;
}
I believe this is due to the "never-empty" guarantee of variant: The default constructor of C must initialize itself with a default-constructed value of its first template parameter - which is recursive_wrapper<A> - and the default constructor of recursive_wrapper<A> must initialize itself with a default-constructed instance of A, which leads to infinite recursion.
Assuming you actually want a variant that is either empty, or an instance of A, you could introduce a dummy type as the variant's first parameter, for example:
struct variant_is_empty { };
using C = boost::variant<variant_is_empty, boost::recursive_wrapper<A>>;
EDIT: It appears you can use boost::recursive_wrapper with boost::optional, which would be easier than using variant for the above case of an optional, recursive type.