Reputation: 9
I have a program which is using an iterator to print objects. The pointers to each object are stored in a vector. When I try to print these objects by dereferencing the iterator, it simply prints the memory location. I believe its because I have one more layer of indirection due to the pointers, but when I dereference again, I get a seg fault that I haven't been able to track down. Can anyone find the problem?
int main(int argc, const char * argv[]){
ObjectFactory* objFact = readInput();
for (ObjectFactory::const_iterator p = objFact->begin(); p!=objFact->end(); ++p){
std::cout << *p << " ";
}
return 0;
}
ObjectFactory* readInput(){
std::vector<MyObject*> myObjects;
ObjectFactory* objFact = ObjectFactory::get_inst();
std::string input;
int years_passed;
std::cin >> years_passed;
std::cin >> input;
int age = 0;
float diameter = 0;
while (std::cin){
try{
if (input == "int"){
int value;
if (std::cin >> value){
if (value > 0){
age = value;
std::cin >> input;
}
else{
std::cin >> input;
throw negativeNumber("integer", value);
}
}
else{
std::cin.clear();
std::cin >> input;
throw missingValue("int", input);
}
}
else if (input == "float"){
float value;
if (std::cin >> value){
if (value > 0){
diameter = value;
std::cin >> input;
}
else{
std::cin >> input;
throw negativeNumber("float", value);
}
}
else{
std::cin.clear();
std::cin >> input;
throw missingValue("float", input);
}
}
else if (input == "string"){
std::string value;
std::cin >> value;
if (diameter == 0 || age == 0){
std::cin >> input;
throw incompleteObject(value);
}
try{
objFact->new_object(value, diameter, age);
}
catch (invalidAge ex){
ex.printMessage();
}
std::cin >> input;
}
else{
std::string tempInput = input;
std::cin >> input;
throw unrecognizedType(tempInput);
}
}
catch (unrecognizedType ex){
ex.printMessage();
}
catch (incompleteObject ex){
ex.printMessage();
}
catch (negativeNumber ex){
ex.printMessage();
}
catch (missingValue ex){
ex.printMessage();
}
}
return objFact;
}
class ObjectFactory {
public:
static ObjectFactory* get_inst();
MyObject* new_object(std::string name, float diameter, int age);
void time_passed(int year);
typedef std::vector<MyObject*>::const_iterator const_iterator;
const_iterator begin() const{return objects.begin();}
const_iterator end() const{return objects.end();}
protected:
ObjectFactory(){}
private:
static ObjectFactory* _instance;
std::vector<MyObject*> objects;
};
ObjectFactory* ObjectFactory::_instance=0;
ObjectFactory* ObjectFactory::get_inst(){
if (_instance ==0) {_instance = new ObjectFactory;}
return _instance;
}
//Create the correct object type based of the name
MyObject* ObjectFactory::new_object(std::string name, float diameter, int age){
if (toupper(name.at(0)) == 'C'){
objects.push_back((MyObject*)new Car(name, diameter, age));
return objects.at(objects.size()-1);
}
if (toupper(name.at(0)) == 'T'){
objects.push_back((MyObject*)new Tiger(name, diameter, age));
return objects.at(objects.size()-1);
}
objects.push_back((MyObject*)new Human(name, diameter, age));
return objects.at(objects.size()-1);
}
void ObjectFactory::time_passed(int year){
for (int i = 0; i < objects.size();i++){
objects[i]->year_passed(year);
if (objects[i]->get_age()>objects[i]->get_max_age()){
delete objects[i];
}
}
}
//Prints output for objecs of MyObject type
std::ostream& operator << (std::ostream& out, MyObject& obj)
{
out << "(" <<obj.get_type_name() << "," << obj.get_name() << "," << obj.get_diameter() << "," << obj.get_age() << ","<< obj.get_speed() << ")";
}
ObjectFactory* ObjectFactory::_instance=0;
ObjectFactory* ObjectFactory::get_inst(){
if (_instance ==0) {_instance = new ObjectFactory;}
return _instance;
}
//Create the correct object type based of the name
MyObject* ObjectFactory::new_object(std::string name, float diameter, int age){
if (toupper(name.at(0)) == 'C'){
objects.push_back((MyObject*)new Car(name, diameter, age));
return objects.at(objects.size()-1);
}
if (toupper(name.at(0)) == 'T'){
objects.push_back((MyObject*)new Tiger(name, diameter, age));
return objects.at(objects.size()-1);
}
objects.push_back((MyObject*)new Human(name, diameter, age));
return objects.at(objects.size()-1);
}
void ObjectFactory::time_passed(int year){
for (int i = 0; i < objects.size();i++){
objects[i]->year_passed(year);
if (objects[i]->get_age()>objects[i]->get_max_age()){
delete objects[i];
}
}
}
//Prints output for objecs of MyObject type
std::ostream& operator << (std::ostream& out, MyObject& obj)
{
out << "(" <<obj.get_type_name() << "," << obj.get_name() << "," << obj.get_diameter() << "," << obj.get_age() << ","<< obj.get_speed() << ")";
}
I didn't include the code for MyObject or its subclasses or the error structs I'm using as it didn't seem relevant, but let me know if you need it.
Upvotes: 0
Views: 2329
Reputation: 206567
The problem is most likely caused by the missing return
statement in
std::ostream& operator << (std::ostream& out, MyObject& obj)
{
out << "(" <<obj.get_type_name() << "," << obj.get_name() << "," << obj.get_diameter() << "," << obj.get_age() << ","<< obj.get_speed() << ")";
}
That would definitely lead to undefined behavior if you use:
std::cout << *(*p) << " ";
Add a return
statement.
Also, I would change obj
to MyObject const&
.
std::ostream& operator << (std::ostream& out, MyObject const& obj)
{
out << "(" <<obj.get_type_name() << "," << obj.get_name() << "," << obj.get_diameter() << "," << obj.get_age() << ","<< obj.get_speed() << ")";
return out;
}
Upvotes: 1