Evan
Evan

Reputation: 9

Dereferencing iterator to pointer

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

Answers (1)

R Sahu
R Sahu

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

Related Questions