Hey all,

I've been programming an ISBN system of sorts and I'm a little stuck (again).


I want to output my linked list to a text file, so I setup the code like this:

void saveList(char fileName[40])
{
	for ( list< Publication* >::iterator it = pubList.begin(); it != pubList.end(); it++)
	{
		try{
			std::ofstream ouf(fileName);
			if( !ouf ) throw std::ios::failure( "File Error" );

                        ouf<<"Publication,"<<(*it)->getPublisher()<<","<<(*it)->getIsbn();
                        ouf.close();
                }catch( const std::exception& e){
			std::cerr <<e.what()<<endl;
		}
         }
}

Now saving like this works alright with a small issue. I can only access the public functions of the base class object, I can't access the public functions of the derived classes. In addition I can't seem to figure out a way to identify which type of object in the list it is.

in this case I want the oustream to work like this:

if object is of type Publication, output all of publications details to a file.
else if object is of type Book output all of books details to a file.
else if type is ProceedingsBook output those details to a file.

The thing is, how exactly do I identify the object type in the list?

For now I'm writing a specific data member (and get function) identifying each type, I was just wondering if there is another way?

First you loop solution is very inefficient, with regards to opening and closing files. Just open it once and close it once.

Next a solution to your problem is to have the classes have its own extraction operator. Check this link for more details.

I forgot to mention in my first post:

Publication is the base class, with Book being derived from Publication and finally I have a class called ProceedingsBook which is derived from Book.

Publication <- Book <- ProceedingsBook

I have a list setup as follows:

list<publication*> pubList;

I can access all of the Publication objects public functions perfectly fine, the issue arises when I try to access a derived object in the Publication list. As I used pointers I know that the list is correctly populated with the relevant object types, e.g. Books, Publications and Proceedingsbook objects.

The issue is, when I iterate through the list and attempt to access a derived class the code spits out a compile time error.

else if((*it)->getType().compare("Book")==0)
{
    ouf<<(*it)->getType()<<","<<(*it)->getPublisher()<<","<<(*it)->getIsbn()<<","
    <<(*it)->getAuthor()<<","<<(*it)->getTitle()<<endl;
}

Spits out the following compile error:
error C2039: 'getAuthor' : is not a member of 'Publication'
see declaration of 'Publication'

The only reason my code can detect which object it is; is because I have used a virtual function to return the data member "_type".

Any help is really appreciated!

Yes I figured from your post that Publication was a base class. If you want to, you can cast the publication to the derived class and take appropriate measure like so:

Book * bk = dynamic_cast(*it);
if(bk != null){
  //publication was a book so do book stuff with 'bk'
}

Edited 5 Years Ago by firstPerson: n/a

First you loop solution is very inefficient, with regards to opening and closing files. Just open it once and close it once.

Next a solution to your problem is to have the classes have its own extraction operator. Check this link for more details.

Thanks a lot for that, readong the article now and it seems very handy, actually I imagine this will come in useful quite often in the future.

First you loop solution is very inefficient, with regards to opening and closing files. Just open it once and close it once.

Next a solution to your problem is to have the classes have its own extraction operator. Check this link for more details.

Actually just tried this in practice. When I use oustream like this:

output<<(*it);

having defined my publication class as

friend ostream& operator<<(ostream &out, const Publication &pub);

ostream& operator<<(ostream &out, const Publication &pub)
{
	out << pub._type<<","<< pub._publisher<<","<<pub._isbn<<endl;
	return out;
}

The file output is a 24 digit hexidecimal number (memory address?)

my brain is exploding!

make sure you aren't creating 'out' over and over again, therefore overwriting data. And post your new code.

I think you should make a method for printing a publication.

class Publication
{
public:
    //Publication doesn't know about what data of subclass should be printed 
    virtual void print(std::ostream& os) const
    {
        os<<isbn<<title;
    }
};

std::ostream& operator<<(std::ostream &os, const Publication &pub)
{
    pub.print(os);
    return out;
}

class Book: public Publication
{
private:
    void print(std::ostream& os) const
    {
        Publication::print(os); //if want isbn and title to be printed.
        //access book data
    }
};

class Magazine: public Publication
{
private:
    void print(std::ostream& os) const
    {
       Publication::print(os); //if want isbn and title to be printed.
       //access magazine data
    }
};

Edited 5 Years Ago by jinhao: n/a

I think you should make a method for printing a publication.

class Publication
{
public:
    //Publication doesn't know about what data of subclass should be printed 
    virtual void print(std::ostream& os) const
    {
        os<<isbn<<title;
    }
};

std::ostream& operator<<(std::ostream &os, const Publication &pub)
{
    pub.print(os);
    return out;
}

class Book: public Publication
{
private:
    void print(std::ostream& os) const
    {
        Publication::print(os); //if want isbn and title to be printed.
        //access book data
    }
};

class Magazine: public Publication
{
private:
    void print(std::ostream& os) const
    {
       Publication::print(os); //if want isbn and title to be printed.
       //access magazine data
    }
};

jinhao, this was exactly what I needed! quite clever aswell. As firstperson suggested, operator overloading was key. I wasn't sure how to apply it to all the derived classes until you showed me. Thankyou to both firstperson and jinhao!

This question has already been answered. Start a new discussion instead.