Thread: virtual functions

  1. #1
    Registered User
    Join Date
    Jul 2007
    Posts
    109

    virtual functions

    Hi, I have make an abstract base class called Holding and I have to make two derived classes that use some virtual functions. I have already made these classes but on top of all this I have to make a library.cpp that uses these functions. The output for the program is very weird. It outputs the first two lines just fine and then where it asks for me to put in b or r I do and sometimes it goes right to asking the book title and sometimes it completely skips over the input and asks for me to put in b or r for book or recording. Rarely, does it go through one loop successfully. Success is when it asks for the book title author and call number and then it asks for another holding. Basically what I am supposed to do for the main function is to declare an array of five pointers to Holding objects an then call a function that makes a new Holding. The function will ask which kind of holding is to be entered and inputs the data to make a book or a recording. Then a new object should be made with this data and the pointer that results should be returned. The function can be declared to return a Holding pointer and the pointer to the newly created object can be returned without conversion. This pointer is stored in the array and the function is called again and again until the five objects have been created. The program should also be able to run through the array and call the virtual print function for each object. I will post all my code below. Again I am having problems with the main function in library.cpp. Thanks.

    Code:
    //holding.h
    
    #ifndef _Holding_H
    #define _Holding_H
    
    #include <iostream>
    
    
    class Holding
    {
    public:
    	Holding();
    	Holding(const char *str);
    	virtual void settitle() =0;
    	virtual void setcallnum() =0;
    	virtual void print() =0;
    	virtual ~Holding();
    
    private:
    	char *buf;
    
    };
    
    #endif
    
    //holding.cpp
    
    #define _CRT_SECURE_NO_DEPRECATE 1
    #include <iostream>
    #include "holding.h"
    
    using namespace std;
    
    Holding::Holding()
    {
    	buf = new char[1];
    	buf[0] = '\0';
    }
    
    Holding::Holding(const char *str)
    {
    	buf = new char[strlen(str) + 1];
    	strcpy(buf, str);
    }
    
    Holding::~Holding()
    {
    	delete []buf;
    }
    
    
    //book.h
    
    #ifndef _Book_H
    #define _Book_H
    
    #include <iostream>
    #include "holding.h"
    
    class Book: public Holding
    {
    public:
    	Book();
    	Book(const char *s);
    	virtual ~Book();
    	virtual void settitle();
    	void setbookauthor();
    	virtual void setcallnum();
    	virtual void print();
    
    private:
    	char booktitle;
    	char bookauthor;
    	char bookcallnum;
    	char *bbuf;
    
    };
    
    #endif
    
    
    //book.cpp
    
    #define _CRT_SECURE_NO_DEPRECATE 1
    #include <iostream>
    #include "book.h"
    
    using namespace std;
    
    Book::Book()
    {
    	bbuf = new char[1];
    	bbuf[0] = '\0';
    }
    
    Book::Book(const char *s)
    {
    	bbuf = new char[strlen(s) + 1];
    	strcpy(bbuf, s);
    }
    
    Book::~Book()
    {
    	delete []bbuf;
    }
    
    void Book::settitle()
    {
    	cout<< "Enter book title: " << endl;
    	cin>> booktitle;
    	cin.get();
    }
    
    void Book::setbookauthor()
    {
    	cout<< "Enter book author: " << endl;
    	cin>> bookauthor;
    	cin.get();
    }
    
    void Book::setcallnum()
    {
    	cout<< "Enter call number: " << endl;
    	cin>> bookcallnum;
    	cin.get();
    }
    
    void Book::print()
    {
    	cout<< "BOOK: """ << booktitle << """" << bookauthor << bookcallnum << endl;
    }
    
    //record.h
    
    #ifndef _Recording_H
    #define _Recording_H
    
    #include <iostream>
    #include "holding.h"
    
    class Recording: public Holding
    {
    public:
    	Recording();
    	Recording(const char *str);	
    	virtual ~Recording();
    	virtual void settitle();
    	void setrecperformer();
    	virtual void setcallnum();
    	void setrecformat();
    	virtual void print();	
    
    private:
    	char rectitle;
    	char recauthor;
    	char reccallnum;
    	char recformat;
    	char *rbuf;
    
    };
    
    #endif
    
    //record.cpp
    
    #define _CRT_SECURE_NO_DEPRECATE 1
    #include <iostream>
    #include "record.h"
    
    using namespace std;
    
    Recording::Recording()
    {
    	rbuf = new char[1];
    	rbuf[0] = '\0';
    }
    
    Recording::Recording(const char *str)
    {
    	rbuf = new char[strlen(str) + 1];
    	strcpy(rbuf, str);
    }
    
    Recording::~Recording()
    {
    	delete []rbuf;
    }
    
    
    void Recording::settitle()
    {
    	cout<< "Enter recording title: " << endl;
    	cin>> rectitle;
    	cin.get();
    }
    
    void Recording::setrecperformer()
    {
    	cout<< "Enter performer: " << endl;
    	cin>> recauthor;
    	cin.get();
    }
    
    void Recording::setcallnum()
    {
    	cout<< "Enter call number: " << endl;
    	cin>> reccallnum;
    	cin.get();
    }
    
    void Recording::setrecformat()
    {
    	cout<< "Enter format: (L)P, (C)assette, (R)eel_to_reel, (D)isk:" << endl;
    	cin>> recformat;
    	cin.get();
    }
    
    void Recording::print()
    {
    	cout<< "RECORDING: """<< rectitle << """" << recauthor << recformat << reccallnum << endl;
    }
    
    //library.h
    
    #include <iostream>
    #include "holding.h"
    #include "book.h"
    #include "record.h"
    
    //library.cpp
    
    #include <iostream>
    #include "library.h"
    
    
    using namespace std;
    
    int main()
    {
    	Holding *ptr[5];
    	Book *bptr;
    	Recording *rptr;
    	char choice;
    	cout<< "Enter holdings to be stored in a list: " << endl;
    	for(int i = 0; i<5; i++)
    	{
    		cout<< "Enter B for book, R for recording: " << endl;
    		cin>> choice;
    		if(choice == 'b' || choice == 'B')
    		{
    			bptr = new Book;
    			bptr->settitle();
    			bptr->setbookauthor();
    			bptr->setcallnum();
    			ptr[i] = bptr;
    
    		}
    		if(choice == 'r' || choice == 'R')
    		{
    			rptr = new Recording;
    			rptr->settitle();
    			rptr->setrecperformer();
    			rptr->setrecformat();
    			rptr->setcallnum();
    			ptr[i] = rptr;
    		}
    
    	}
    	for(int k = 0; k<5; k++)
    		ptr[k]->print;
    }

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Your classes seem to have lots of (single) char members for things that normally need something larger. Is there any reason you don't use std::string, so you can be sure that everything is OK on the low-level side?

    After fixing this
    Code:
    for(int k = 0; k<5; k++)
        ptr[k]->print();
    everything seemed to work fine for me, as long as I remembered to type a single character for everything.
    Last edited by anon; 08-11-2007 at 04:50 PM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by anon View Post
    Your classes seem to have lots of (single) char members for things that normally need something larger. Is there any reason you don't use std::string, so you can be sure that everything is OK on the low-level side?
    Do you think the reason I am having these problems is because I am using char? How would I use std::string instead?

  4. #4
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    I just noticed something. My program runs perfectly if I only put in one letter for each input. What does this mean and how do I fix it?

  5. #5
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by BKurosawa View Post
    I just noticed something. My program runs perfectly if I only put in one letter for each input. What does this mean and how do I fix it?
    In addition, I found the program also works perfectly if I do not have any spaces in any of my words. The problem arises when I try to do spaces. How do I fix this?

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I just couldn't understand how you would store a title or an author in a single character. And what are the buf members for?

    Another bug is that if you don't type B or R, you'll have an uninitialized pointer in the array.

    May-be you could post sample input/output that you are seeing...


    Edit:
    Didn't see your previous replies.

    A char can only hold a single character. To hold strings, use the std::string type. To read a whole line of input (strings with spaces), use std::getline (string version).
    Last edited by anon; 08-11-2007 at 05:07 PM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    Quote Originally Posted by anon View Post
    I just couldn't understand how you would store a title or an author in a single character. And what are the buf members for?

    Another bug is that if you don't type B or R, you'll have an uninitialized pointer in the array.

    May-be you could post sample input/output that you are seeing...


    Edit:
    Didn't see your previous replies.

    A char can only hold a single character. To hold strings, use the std::string type. To read a whole line of input (strings with spaces), use std::getline (string version).
    I didn't actually put a real author name when I was inputting the authors name... I used random letters.
    >> another bug is that if you don't type B or R, you'll have an uninitialized pointer in the array.
    Thanks but I don't have to worry about that.

    Here is a part of the output. The first part is without spaces and the second is with spaces:
    Enter holdings to be stored in a list:
    Enter B for book, R for recording:
    B
    Enter book title:
    United
    Enter book author:
    Patterson
    Enter call number:
    121
    Enter B for book, R for recording:
    b
    Enter book title:
    Jack and Jill
    Enter book author:
    Enter call number:
    Enter B for book, R for recording:

    The problem is that when I put in spaces the program skips ahead. I don't know what the problem is or how to fix it. Thanks

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Code:
    std::string s;
    std::cin >> s; //reads input up to the first whitespace
    std::getline(std::cin, s); //reads a whole line with spaces
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    Registered User
    Join Date
    Jul 2007
    Posts
    109
    I changed my code (see below) and there are still problems. Namely, It completely skips over the input for the author and the performer. For example, say I put in B for book then the next output is:

    Enter book title: Enter book author:

    I can then input data for the author but I can't put in anything for book title. Why is it doing that. My complete code is below. Thank You!

    Code:
    //holding.h
    
    #ifndef _Holding_H
    #define _Holding_H
    
    #include <iostream>
    
    
    class Holding
    {
    public:
    	Holding();
    	Holding(const char *str);
    	virtual void settitle() =0;
    	virtual void setcallnum() =0;
    	virtual void print() =0;
    	virtual ~Holding();
    
    private:
    	char *buf;
    
    };
    
    #endif
    
    
    //holding.cpp
    
    #define _CRT_SECURE_NO_DEPRECATE 1
    #include <iostream>
    #include "holding.h"
    
    using namespace std;
    
    Holding::Holding()
    {
    	buf = new char[1];
    	buf[0] = '\0';
    }
    
    Holding::Holding(const char *str)
    {
    	buf = new char[strlen(str) + 1];
    	strcpy(buf, str);
    }
    
    Holding::~Holding()
    {
    	delete []buf;
    }
    
    //book.h
    
    #ifndef _Book_H
    #define _Book_H
    
    #include <iostream>
    #include <string>
    #include "holding.h"
    
    class Book: public Holding
    {
    public:
    	Book();
    	Book(const char *s);
    	virtual ~Book();
    	virtual void settitle();
    	void setbookauthor();
    	virtual void setcallnum();
    	virtual void print();
    
    private:
    	std::string booktitle;
    	std::string bookauthor;
    	std::string bookcallnum;
    	char *bbuf;
    
    };
    
    #endif
    
    //book.cpp
    
    #define _CRT_SECURE_NO_DEPRECATE 1
    #include <iostream>
    #include <string>
    #include "book.h"
    
    using namespace std;
    
    Book::Book()
    {
    	bbuf = new char[1];
    	bbuf[0] = '\0';
    }
    
    Book::Book(const char *s)
    {
    	bbuf = new char[strlen(s) + 1];
    	strcpy(bbuf, s);
    }
    
    Book::~Book()
    {
    	delete []bbuf;
    }
    
    void Book::settitle()
    {
    	cout<< "Enter book title: ";
    	std::getline(cin, booktitle);
    
    }
    
    void Book::setbookauthor()
    {
    	cout<< "Enter book author: ";
    	std::getline(cin, bookauthor);
    }
    
    void Book::setcallnum()
    {
    	cout<< "Enter call number: ";
    	std::getline(cin, bookcallnum);
    }
    
    void Book::print()
    {
    	cout<< "BOOK: "<< booktitle << "      " << bookauthor << "      " << bookcallnum << "      " << endl;
    }
    
    //record.h
    
    #ifndef _Recording_H
    #define _Recording_H
    
    #include <iostream>
    #include <string>
    #include "holding.h"
    
    class Recording: public Holding
    {
    public:
    	Recording();
    	Recording(const char *str);	
    	virtual ~Recording();
    	virtual void settitle();
    	void setrecperformer();
    	virtual void setcallnum();
    	void setrecformat();
    	virtual void print();	
    
    private:
    	std::string rectitle;
    	std::string recauthor;
    	std::string reccallnum;
    	std::string recformat;
    	char *rbuf;
    
    };
    
    #endif
    
    //record.cpp
    
    #define _CRT_SECURE_NO_DEPRECATE 1
    #include <iostream>
    #include "record.h"
    
    using namespace std;
    
    Recording::Recording()
    {
    	rbuf = new char[1];
    	rbuf[0] = '\0';
    }
    
    Recording::Recording(const char *str)
    {
    	rbuf = new char[strlen(str) + 1];
    	strcpy(rbuf, str);
    }
    
    Recording::~Recording()
    {
    	delete []rbuf;
    }
    
    
    void Recording::settitle()
    {
    	cout<< "Enter recording title: ";
    	std::getline(cin, rectitle);
    }
    
    void Recording::setrecperformer()
    {
    	cout<< "Enter performer: ";
    	std::getline(cin, recauthor);
    }
    
    void Recording::setcallnum()
    {
    	cout<< "Enter call number: ";
    	std::getline(cin, reccallnum);
    }
    
    void Recording::setrecformat()
    {
    	cout<< "Enter format: (L)P, (C)assette, (R)eel_to_reel, (D)isk:" ;
    	std::getline(cin, recformat);
    }
    
    void Recording::print()
    {
    	cout<< "RECORDING: "<< rectitle << recauthor << recformat  << reccallnum << endl;
    }
    
    
    //library.h
    
    #include <iostream>
    #include "holding.h"
    #include "book.h"
    #include "record.h"
    
    //library.cpp
    
    #include <iostream>
    #include "library.h"
    
    
    using namespace std;
    
    int main()
    {
    	Holding *ptr[5];
    	Book *bptr;
    	Recording *rptr;
    	char choice;
    	cout<< "Enter holdings to be stored in a list: " << endl;
    	for(int i = 0; i<5; i++)
    	{
    		cout<< "Enter B for book, R for recording: ";
    		cin>> choice;
    		if(choice == 'b' || choice == 'B')
    		{
    			bptr = new Book;
    			bptr->settitle();
    			bptr->setbookauthor();
    			bptr->setcallnum();
    			ptr[i] = bptr;
    
    		}
    		if(choice == 'r' || choice == 'R')
    		{
    			rptr = new Recording;
    			rptr->settitle();
    			rptr->setrecperformer();
    			rptr->setrecformat();
    			rptr->setcallnum();
    			ptr[i] = rptr;
    		}
    
    	}
    	for(int k = 0; k<5; k++)
    		ptr[k]->print();
    }

  10. #10
    The larch
    Join Date
    May 2006
    Posts
    3,573
    That has to do with inputting with cin (namely mixing >> and getline). Each time after getting input with >> (and before using getline), you should clear the input buffer of any other characters it might contain (e.g new line) with ignore.

    Your first getline is skipped, because the input stream already contains a '\n' (left by >> when you typed Enter), which it happily reads, puts nothing in the string and throws away the '\n'.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. i need a good example of virtual functions
    By Anddos in forum C++ Programming
    Replies: 10
    Last Post: 02-15-2006, 11:48 AM
  2. Virtual Functions
    By guda in forum C++ Programming
    Replies: 3
    Last Post: 11-16-2004, 04:13 PM
  3. Thread creation on virtual functions
    By gustavosserra in forum C++ Programming
    Replies: 13
    Last Post: 10-14-2004, 08:03 AM
  4. recursive virtual functions
    By ygfperson in forum C++ Programming
    Replies: 0
    Last Post: 05-25-2003, 08:00 PM
  5. Exporting Object Hierarchies from a DLL
    By andy668 in forum C++ Programming
    Replies: 0
    Last Post: 10-20-2001, 01:26 PM