So, here's my code:
/****************************************************************
File: Video.h
Description: class declarations
Author: David && Evan
Class: CSCI 120
Date: 2015 May 13
We hereby certify that this program is entirely our own work.
*****************************************************************/
#ifndef VIDEO_H
#define VIDEO_H
#include <iostream>
#include <string>
#include <vector>
#include "Person.h"
#include "Date.h"
using namespace std;
enum kind {MOVIE, TELEVISION, COMPUTER};
// 'MOVIE' = standalone film of any length, whether it's part of a franchise or not
// 'TELEVISION' = episode from mini- or recurring series
// 'COMPUTER' = online or locally hosted files
/* If need be, we can extend this by adding something for analog home movies,
i.e., camcorder tapes or 8mm film. */
namespace Vids
{
class Video{
public:
Video(); // default constructor
Video(string name, string audience, string location, vector<Person> directors,
vector<Person> actors, Date released);
virtual void display() = 0; // displays information for all objects of Video type
virtual void displayAll() = 0; // displays all information for one object
unsigned char getDirectorSize() const { return directorSize; }
unsigned char getActorSize() const { return actorSize; }
string getName() const { return name; }
string getAudience() const { return audience; }
string getLocation() const { return location; }
Date getReleased() const { return released; }
Date getViewed() const { return viewed; }
string Truncate(string str, size_t width) { // shortens output
if (str.length() > width)
return str.substr(0, width) + "...";
return str;
} // truncate
protected:
short runtimeMinutes;
/* Theoretically runtime could be unsigned, but we might eventually
need negatives for special values. I doubt we'll see one needing
more than 32K minutes, so no worry about overflow. */
unsigned char directorSize;
// number of elements in each vector, shouldn't need more than 255
unsigned char actorSize;
string name; // title of movie
string audience; // PG = "Plenty Guns", PG-13 = "13 or more guns"
string location;
/* Location is a catch-all field for: URL, shelf disc is on, format
type, name of person it is loaned to, etc. */
vector<Person> directors(directorSize);
/* David: I considered using other containers, but none of them
offered any obvious benefits over the vector. */
vector<Person> actors(actorSize);
Date released;
Date viewed;
/* 'viewed' can be used to answer the question: "What haven't i
watched lately?" */
}; // end class Video
} // end namespace Vids
#endif
And compiling [with several other files] gives me this:
$ g++ *.cpp -o Project3
In file included from Computer.cpp:12:
In file included from ./Computer.h:15:
./Video.h:68:29: error: unknown type name 'directorSize'
vector<Person> directors(directorSize);
^
./Video.h:71:26: error: unknown type name 'actorSize'
vector<Person> actors(actorSize);
^
directorSize is declared in the same scope as directors, so why is the compiler not recognizing it?
The line
vector<Person> directors(directorSize);
is not the right syntax for declaring a member variable.
Change it to
vector<Person> directors;
Similarly, change
vector<Person> actors(actorSize);
to
vector<Person> actors;
Given that you can get the number of items in a vector by calling the size() member function, you don't need the member variables:
unsigned char directorSize;
unsigned char actorSize;
Remove them.
Well, this comment is puzzling:
/* Theoretically runtime could be unsigned, but we might eventually
need negatives for special values. I doubt we'll see one needing
more than 32K minutes, so no worry about overflow. */
unsigned char directorSize;
unsigned char maxes out at 255 so if you need up to 32K then you will have to use a different type. In fact it would be better to remove this variable entirely, and retrieve the size by doing directors.size() as needed.
It is possible to initialize the vector in the class definition:
vector<Person> directors{directorSize};
However this would cause undefined behaviour if you hadn't initialized directorSize in the constructor initializer list (because you would be using an uninitialized variable directorSize).
It would be much better to change this to:
vector<Person> directors;
and presumably in your constructor initializer list, or constructor body, you will add some items into this vector.
I'll boil your problem down to a trivial case to demonstrate the problem, along with applying the "m_" member variable prefix popular among some engineers for highlighting a variable that is a "member" of something.
#include <vector>
class Class {
protected:
unsigned char m_directorSize;
std::vector<int> m_directors(m_directorSize);
};
int main()
{
Class x;
}
This does not compile http://ideone.com/VJck4Q and by isolating the problem, we learned a lot.
The line of code:
std::vector<int> m_directors(m_directorSize);
Look at the syntax of this
/typename/ /name/ ( /values/ );
The compiler thinks this is a member-function declaration, which is why it is expecting a type:
std::vector<int> something(unsigned char directorSize);
would declare a member-function called "something" that takes a parameter, directorSize, of type unsigned char. Incidentally: unsigned char is almost guaranteed to be an 8-bit value, capable of storing 0 through 255. That's a terrible choice for a size variable. There is a standard type, size_t for storing non-negative sizes and ssize_t for storing signed sizes.
It's unclear why you think you should be passing directorSize to the vector, but you can't declare a member with a function call.
If you want to shape the default behavior of an object at construction time of your class, you need to use a constructor (or use C++11/C++14, but we don't know if you're doing that):
class Foo_Sized {
std::vector<int> m_vec;
public:
Foo() : m_vec(250) // default construct 250 elements
{}
};
If you were using C++11/14:
class Foo_Sized {
std::vector<int> m_vec = std::vector<int>(250);
};
But if you want to affect one member based on the value of another, the only place you can do that is in a member function, so in this case that means the constructor.
If you're going to create a static array like that, you probably want to be using std::array instead of std::vector - the whole point of vector is that it can grow dynamically.
std::array<int, 250> m_arr;
This declares an array of integers which has a capacity of 250 and has a fixed size. It's faster than a vector but it is always 250 large. You would then have to track the "in-use" count of it and other management overhead yourself.
std::vector<int> vec;
std::cout << vec.size() << '\n'; // prints 0
vec.push(10); // add a value of 10 to the vector.
vec.push(20); // vec is now { 10, 20 }
std::cout << vec.size() << '\n'; // prints 2
vec.push(30); // vec is now { 10, 20, 30 }
std::cout << vec.size() << '\n'; // prints 3
std::cout << vec[0] << '\n'; // prints 10
std::cout << vec[3] << '\n'; // undefined behavior, there is no 3rd element
std::array<int, 3> arr;
std::cout << arr.size() << '\n'; // prints 3: fixed size.
arr[0] = 10; // can't push, fixed size.
arr[1] = 20;
std::cout << arr.size() << '\n'; // still 3, always will be.
arr[2] = 30;
std::cout << arr.size() << '\n'; // still 3, always will be.
std::cout << arr[0] << '\n'; // prints 10
std::cout << arr[3] << '\n'; // compile error: outside fixed size
If you were worrying about memory allocation, you could tell the vector to allocate memory upfront like this:
class Foo_Reserved {
std::vector<int> m_vec;
public:
Foo() : m_vec() // default construct empty
{
m_vec.reserve(250); // reserve memory for 250 elements
}
};
There are a host of other issues with your code, but they aren't directly related to your question so I'm not going to address/highlight them.
But in terms of dealing with your directorSize issues, you should consider providing an accessor that queries the vector or expose a const reference to the vector (this somewhat breaks encapsulation tho since it allows external callers to write code based on assumptions about your internal structure).
class Foo {
public:
using vec_t = std::vector<int>;
protected:
vec_t m_vec;
public:
Foo() : m_vec() // default construct empty
{
}
size_t vecSize() const { return m_vec.size(); }
// or, return a look-don't-touch reference to the vector
const vec_t& getVec() const { return m_vec; }
};
Foo f{}; // C++14 initializer
f.vecSize();
f.getVec().size();
Related
I've began making a program in linux with c++ and I'm trying to make it work on windows. It compiles fine, but when run I get this error: "1 [main] Trails of Cold Steel Simulator 8748 cygwin_exception::open_stackdumpfile: Dumping stack trace to Trails of Cold Steel Simulator.exe.stackdump". In the stack trace this exception occurs: "Exception: STATUS_ACCESS_VIOLATION". Here's some code;
#include "Tachi.h"
#include "AutumnLeafCutter.h"
#include <iostream>
#include "Weapon.h"
#include "Armour.h"
#include "Shoes.h"
int main() {
int stats[12] = {15,110,10,4,2,1,2,4,4,3,7,1};
Tachi* Tachi1 = new Tachi(stats, "Tachi");
Tachi1->addEquipment(new PracticeSword());
Tachi1->addEquipment(new LeatherJacket());
Tachi1->addEquipment(new WorkBoots());
Tachi1->addMasterQuartz(new Forcelvl1());
std::string input;
std::cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
while(input != "q") {
std::cout << "Your current stats are:" << std::endl;
std::cout << "\n";
std::cout << "HP EP STR DEF ATS ADF SPD DEX AGL MOV RNG" << std::endl;
for(int i = 0; i < 12; i += 1) {
std::cout << Tachi1->getBaseStats()[i] << " ";
}
std::cout << "\n\n";
std::cout << "Select a Craft by typing its name:" << std::endl;
std::cout << std::endl;
for(int i = 0; i < Tachi1->getCrafts().size(); i++) {
std::cout << Tachi1->getCrafts()[i]->getName() << std::endl;
}
std::cout << std::endl;
getline(std::cin, input);
if(Tachi1->findCraft(input) != NULL) {
Tachi1->useCraft(input);
} else {
std::cout << "You do not have this craft." << std::endl;
}
std::cout << "\n\n\n";
}
}
Im extremely sorry for any formatting, I've never posted here. The error comes from lines 14,15,16 and 18. When I replaced all the "new xxx()" with NULL and comment out the body of the function with them, the program works. It does this for both addEquipment() and addMasterQuartz(). This is the functions;
void Character::addEquipment(Equipment* e) {
equipment.push_back(e);
std::cin.get();
for(int i = 0; i < 12; i++) {
baseStats[i] += equipment[equipment.size()]->getStatsModifier()[i];
}
}
and
void Character::addMasterQuartz(MasterQuartz* mq) {
masterQuartz = mq;
for(int i = 0; i < 12; i++) {
baseStats[i] += masterQuartz->getStatsModifier()[i];
}
}
Im guessing its a problem with the baseStats[i] += xxx stuff as its the only thing that occurs in both, but I have no idea how to fix that. It could also occur when the stuff is made using new xxx().
I can provide whatever else is needed. Thanks!!!!
EDIT:
I kept testing and the problem seems to lie in the creating of the objects. It worked on linux. Here is one of the object codes, they are all similiar and all crash the program;
#include "Armour.h"
Armour::Armour(int* sm, std::string n):Equipment(sm, n) {}
LeatherJacket::LeatherJacket():Armour(stats, armourName) {}
with header file;
#ifndef ARMOUR_H
#define ARMOUR_H
#include "Equipment.h"
class Armour:public Equipment {
public:
Armour(int* sm, std::string n);
};
class LeatherJacket:public Armour {
int stats[12] = {0,0,0,5,0,0,0,0,0,0,0,0};
std::string armourName = "Leather Jacket";
public:
LeatherJacket();
};
#endif
As soon as I remembered I did this I tried compiling (I think) with -std=c++11, it didnt help.
This is your error
baseStats[i] += equipment[equipment.size()]->getStatsModifier()[i];
By definition this is an out of bounds access on your vector, if a vector has a certain size, then the valid indexes are 0 to size - 1, not 0 to size.
It's fairly obvious that you wanted to access the last item in the vector. You can do that like this
baseStats[i] += equipment[equipment.size() - 1]->getStatsModifier()[i];
but even clearer is to use the back method.
baseStats[i] += equipment.back()->getStatsModifier()[i];
Another way would be to use the e variable you've just pushed onto the vector.
baseStats[i] += e->getStatsModifier()[i];
Adding some detail to the problem spotted by Useless, this code is incorrect.
class LeatherJacket : public Armour {
int stats[12] = {0,0,0,5,0,0,0,0,0,0,0,0};
std::string armourName = "Leather Jacket";
public:
LeatherJacket();
};
LeatherJacket::LeatherJacket() : Armour(stats, armourName) {}
The problem is the order in which things happen. First the Armour constructor is called, then the stats and armourName variables are initialised. So the call to the Armour constructor is using uninitiialised variables and will likely crash.
Several solutions possible, the best is probably to use virtual functions.
Making a couple of assumptions about Equipment (which isn't specified the question) it seems you should do something like this.
// header file
class Equipment
{
public:
virtual ~Equipment() {}
virtual std::string getName() const = 0;
virtual const int* getStatsModifier() const = 0;
};
class Armour : public Equipment
{
};
class LeatherJacket : public Armour
{
static const int stats[12];
public:
virtual std::string getName() const { return "Leather Jacket"; }
virtual const int* getStatsModifier() const { return stats; }
};
// source file
const int LeatherJacket::stats[12] = {0,0,0,5,0,0,0,0,0,0,0,0};
This answer adds pure virtual functions to the base class Equipment (which has become an interface), and implements those functions in LeatherJacket. Because the functions are virtual the appropriate function will always be called and there no need to pass the information down to Equipment. Also since it seems to be per-class constant data, stats has been made static const. Until you get to C++17 static const arrays must be defined in a source file, not the header file, as shown above.
Firstly, I'm going to replace the int[12] arrays with a proper type. Partly so the magic number 12 isn't littered all over the code and hard to change later, and partly because it will behave better (ie, not decay to a pointer in some contexts). This needs C++11.
#include <array>
using Stats = std::array<int, 12>;
To me it looks like Armour should have stats and a name, initialized from the arguments passed to its constructor (which you currently ignore).
Like so:
class Armour: public Equipment {
public:
Stats m_stats;
std::string m_name;
Armour(Stats const& s, std::string const &n) : m_stats(s), m_name(n) {}
};
You were already passing those two arguments to the constructor - you just weren't doing anything with them. Now you are.
This means that when we later have leather, scale, chain and plate subclasses, I can have a pointer of type Armour* and not need to worry about which subclass I'm looking at: the stats are available right there in the base class.
I made the members public, which is generally bad style, to save space. It might not matter for your use. I named the members with the m_ prefix so they can't accidentally get confused with similarly-named non-members. It's broadly good style but not essential.
LeatherArmour doesn't need an additional copy per instance, it just needs one of each for the whole class - so they should be const static members.
class LeatherJacket: public Armour {
static const Stats stats {0,0,0,5,0,0,0,0,0,0,0,0};
static const std::string name{"Leather Jacket"};
public:
LeatherJacket() : Armour(stats, name) {}
};
I made the LeatherJacket-specific stat values static const by writing static const in front of them.
The static means that every LeatherJacket has the same base stats, so you don't need a copy per instance, just one copy for the whole class. It's const because the base stats for leather jackets never change over time. You still have the base class member Armour::m_stats which can change as your individual leather jacket gets damaged, repaired, buffed or whatever.
Again, the LeatherJacket constructor was already passing (the equivalent of) these members to the base class constructor, but now they already exist (see the link above about static storage duration). The original instance variables didn't exist when you used them, because the derived (LeatherJacket) object and its data members aren't really constructed until after the base class subobject.
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());
This question already has answers here:
Correct way of initializing a struct in a class constructor
(5 answers)
Closed 8 years ago.
So I read about Plain Old Data classes (POD) , and decided to make my structs POD to hold data. For example, I have
struct MyClass {
int ID;
int age;
double height;
char[8] Name;
};
Obviously, to assign values to the struct, I can do this:
MyClass.ID = 1;
MyClass.age = 20;
...
But is there anyway to assign raw data, WITHOUT knowing the name of each field?
For example, My program retrieves field value for each column,, and I want to assign the value to the struct, given that i don't know the name of the fields..
MyClass c;
while (MoreColumns()) {
doSomething( c , GetNextColumn() ); //GetNextColumn() returns some value of POD types
}
I'm assuming there's way to do this using memcpy, or something std::copy,, but Not sure how to start..
Sorry if the question is a bit unclear.
You can use aggregate initialization:
MyClass c1 = { 1, 20, 6.0, "Bob" };
MyClass c2;
c2 = MyClass{ 2, 22, 5.5, "Alice" };
There is no general way to loop over the members of a struct or class. There are some tricks to add data and functions to emulate that sort of thing, but they all require additional setup work beyond just declaring the type.
Since MyClass is an aggregate, you can use a brace-initializer to initialize all fields in one call, without naming any of them:
MyClass m {
1,
2,
42.0,
{ "Joseph" }
};
However, given your description, maybe a POD is not a good idea, and you might want to design a class with accessors to set internal fields based on (for example) index columns.
Maybe boost::fusion can help you with what you want to archive.
You can use the adapt macro to iterate over a struct.
From the example of boost:
struct MyClass
{
int ID;
int age;
double height;
};
BOOST_FUSION_ADAPT_STRUCT(
MyClass,
(int, ID)
(int, age)
(double, height)
)
void fillData(int& i)
{
i = 0;
}
void fillData(double& d)
{
d = 99;
}
struct MoreColumns
{
template<typename T>
void operator()(T& t) const
{
fillData(t);
}
};
int main()
{
struct MyClass m = { 33, 5, 2.0 };
std::cout << m.ID << std::endl;
std::cout << m.age << std::endl;
std::cout << m.height << std::endl;
MoreColumns c;
boost::fusion::for_each(m, c);
std::cout << m.ID << std::endl;
std::cout << m.age << std::endl;
std::cout << m.height << std::endl;
}
What you are trying to achieve usually leads to hard-to-read or even unreadable code. However, assuming that you have a genuinely good reason to try to assign (as opposed to initialize) raw data to a field without knowing its name, you could use reinterpret_cast as below (Link here). I don't recommend it, but just want to point out that you have the option.
#include <cstdio>
#include <cstring>
struct Target { // This is your "target"
char foo[8];
};
struct Trap {
// The "trap" which lets you manipulate your target
// without addressing its internals directly.
// Assuming here that an unsigned occupies 4 bytes (not always holds)
unsigned i1, i2;
};
int main() {
Target t;
strcpy(t.foo, "AAAAAAA");
// Ask the compiler to "reinterpet" Target* as Trap*
Trap* tr = reinterpret_cast<Trap*>(&t);
fprintf(stdout, "Before: %s\n", t.foo);
printf("%x %x\n", tr->i1, tr->i2);
// Now manipulate as you please
// Note the byte ordering issue in i2.
// on another architecture, you might have to use 0x42424200
tr->i1 = 0x42424242;
tr->i2 = 0x00424242;
printf("After: %s\n", t.foo);
return 0;
}
This is just a quick example I came up with, you can figure out how to make it "neater". Note that in the above, you could also access target iteratively, by using an array in "Trap" instead of i1, i2 as I have done above.
Let me reiterate, I don't recommend this style, but if you absolutely must do it, this is an option you could explore.
I want to create a fixed number of instances of a given class and each time I create one I want to add it to a vector which is a static member in the same class. I tried the following code but it doesn't seem to work (in the main function the Column::GetColumns() call returns an empty vector) plus it leaks memory (Valgrind complains about kUsername not being destroyed).
Any suggestion is highly appreciated!
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::endl;
using std::string;
using std::vector;
class Column {
public:
static const Column kUsername;
static const Column kPassword;
static vector<Column*> GetColumns() {
return columns_;
}
string GetColumnName() const {
return column_name_;
}
private:
static vector<Column*> columns_;
explicit Column(const string& column_name) : column_name_(column_name) {
columns_.push_back(this);
}
Column(const Column& column) : column_name_(column.column_name_) {}
virtual ~Column() {}
string column_name_;
};
const Column Column::kUsername("Username");
const Column Column::kPassword("Password");
vector<Column*> Column::columns_;
int main(void) {
cout << Column::kUsername.GetColumnName() << endl;
cout << Column::kPassword.GetColumnName() << endl;
const vector<Column*>& columns = Column::GetColumns();
for (vector<Column*>::const_iterator it = columns.begin();
it != columns.end();
++it) {
cout << (*it)->GetColumnName() << endl;
}
return 0;
}
You're relying on a particular order of initialization for your static objects. On these two lines:
const Column Column::kUsername("Username");
const Column Column::kPassword("Password");
You are calling this constructor:
explicit Column(const string& column_name) : column_name_(column_name) {
columns_.push_back(this);
}
This assumes that the object columns_ has been initialized already. Apparently, it has not. Read this: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14 from 10.14 through 10.18
The reason that you're not getting the words "Username" and "Password" printed twice is because of a problem with the ordering and initialization of your static objects. What's occuring right now is that your two objects Column::kUsername and then Column Column::kPassword are being initialized before main() is run, and when their constructors are called, they are adding the address of their objects to the Column::columns_ vector object. But the constructor for Column::columns_ hasn't been called yet due to the compiler's selected initialization order of the static objects in the code module ... So when the compiler does actually call the constructor for Column::columns_, it re-initializes the values of the vector, and you therefore loose the memory that was already allocated to save the values of the two pointers you pushed back during the constructors of Column::kUsername and Column Column::kPassword ... this is why Valgrind is complaining about leaked memory ... the vector wasn't properly destructed before it was re-initialized by the call to the vector's default constructor during the static object initialization stage performed by the compiler.
I have a class State that has a string data type called moveType. In the implementation of my code, I am calling a setter void setMoveType(string _moveType); and it's implemented with just moveType = _moveType;
When I call my getter string getMoveType() const; on an instance of State and output it to cout, nothing is displayed.
I am couting upon entering the getMoveType() function. The parameter indeed has the correct value, but it appears that it's not getting set at all.
Does anyone have any idea? I feel this is something simple/trivial in c++ that I'm just completely forgetting.
string State::getMoveType() const {
return moveType;
}
void State::setMoveType(string move_type) {
cout << "In setMoveType and param = " << move_type << endl;
moveType = move_type;
}
std::cout << vec_possibleSuccessors[i].getMoveType() << endl; // within loop;
vector<State> vec_possibleSuccessors;
if (_minState.canMoveUp()) {
up = _minState.moveUp();
up.setMoveType("UP");
up.setF(f(up));
vec_possibleSuccessors.push_back(up);
}
In the above code, _minState and up are instances of State. Also, I have made sure that my copy constructor and assignment operator have been modified to include moveType assignments.
There isn't really enough code to know for sure, but I have a guess: Either you actually assigned to a shadowed variable in the "set" function and never set the class attribute at all, or your State object has actually been destroyed and the string becomes empty (since being empty is one possible option when using destroyed memory).
Well not an answer but a short example that works the way you seem to intend this to work:
#include <string>
class State
{
private:
std::string m_moveType;
public:
State() : m_moveType( "unknown" ) {}
std::string getMoveType() const { return m_moveType; }
void setMoveType( const std::string& moveType ) { m_moveType = moveType; }
};
In your main function or were else you need a vector of States you could write this:
#include <iostream>
#include <vector>
#include "State.h"
int main()
{
std::vector< State > states;
for( int i=0; i<10; ++i )
{
State newState;
newState.setMoveType( "state" );
states.push_back( newState );
}
// do whatever you need to do....
std::vector< State >::iterator it;
std::vector< State >::iterator end = states.end();
for( it=states.begin(); it != end; ++it )
std::cout << (*it).getMoveType() << std::endl;
return 0;
}
A few remarks:
passing parameters by value like setMoveType( string s ) is not
adviseable, pass const references instead. Passing by value incurrs a
full copy of the passed object
be careful with includes and namespaces, in doubt take the extra time
to type std::... if you intend to use a feature defined in namespace
std, and never type using namespace std in a header file.
initialize private members to a sensible default and do it in the class
initializer list
I'm not sure on this either, but you appear to be storing this State in a vector. Could you post the code to how you set elements in the vector? Its important to note that you can't update an element in a vector once its inserted (unless you store a pointer to the element). Also depending upon how you call set, there may be problems.