Thread: Does this class look fine?

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    610

    Does this class look fine?

    Code:
    #ifndef FILEIODATA_H
    #define FILEIODATA_H
    
    template <class T>
    class FileIOData {
    	
    public:
    
    	FileIOData() {};
    	
    	bool WriteToFile (std::ostream& out, T& data)
    	{
    		out << data;	
    		return out.fail();
    	}
    
    	bool ReadFromFile (std::istream& in, T& data)
    	{
    		in >> data;	
    		return in.fail();
    	}
    };
    
    #endif 
    Will handle all the file reads/writes for all my classes

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Why is it a class to begin with? It looks like they are better off as free functions, possibly within a namespace (if they exist at all, since they are almost the same as just using operator<< and operator>> directly, unless you have say, some logging functionality that is not yet implemented). Also, note that WriteToFile should take a const reference since it does not modify data.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by laserlight View Post
    Why is it a class to begin with? It looks like they are better off as free functions, possibly within a namespace (if they exist at all, since they are almost the same as just using operator<< and operator>> directly, unless you have say, some logging functionality that is not yet implemented). Also, note that WriteToFile should take a const reference since it does not modify data.
    Using this example, how do i declare them in a namespace? please show

  4. #4
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Just for silly sake, would this work?

    Code:
    // Class IOData: Handles the input/ouput of data to files
    
    #ifndef FILEIODATA_H
    #define FILEIODATA_H
    
    template <class T>
    class FileIOData {
    	
    public:
    
    	FileIOData(T& obj)  {
    		setClassObj<T>(obj);
    	}
    	
    	~FileIOData() {};
    	
    	bool WriteToFile (std::ostream& out)
    	{
    		out << classObject;	
    		return out.fail();
    	}
    
    	bool ReadFromFile (std::istream& in)
    	{
    		in >> classObject;	
    		return in.fail();
    	}
    
    	T getClassObj() {
    		return classObject;
    	}
    
    	void setClassObj(T obj) {
    		classObject = obj;
    	}
    
    private:
    	T  classObject;
    };
    
    #endif

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Using this example, how do i declare them in a namespace?
    Something like this:
    Code:
    #ifndef FILEIODATA_H
    #define FILEIODATA_H
    
    #include <ostream>
    #include <istream>
    
    namespace FileIOData
    {
        template<typename T>
        bool WriteToFile(std::ostream& out, const T& data)
        {
            out << data;
            return out.fail();
        }
    
        template<typename T>
        bool ReadFromFile(std::istream& in, T& data)
        {
            in >> data;
            return in.fail();
        }
    }
    
    #endif
    Just for silly sake, would this work?
    Test before asking.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by laserlight View Post
    Something like this:
    Code:
    #ifndef FILEIODATA_H
    #define FILEIODATA_H
    
    #include <ostream>
    #include <istream>
    
    namespace FileIOData
    {
        template<typename T>
        bool WriteToFile(std::ostream& out, const T& data)
        {
            out << data;
            return out.fail();
        }
    
        template<typename T>
        bool ReadFromFile(std::istream& in, T& data)
        {
            in >> data;
            return in.fail();
        }
    }
    #endif
    Is this a .h file or .cpp? or doesn't matter ...


    Test before asking.
    I think i shouldn't have said silly sake, then u wud have given me a diff ans , anyway, was asking the syntax ... but will go the namespace route ...thnx

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    That would be the header file (since they're templates!)...
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by Elysia View Post
    That would be the header file (since they're templates!)...
    And this?

    Code:
    #ifndef VALIDATOR_H
    #define VALIDATOR_H
    
    #include <boost/regex.hpp>
    #include <string>
    
    namespace Validator
    {
    	// Validate RSA land line number 
    	bool landLineValidator(const std::string& lndln)
    	{
    		static const boost::regex e("(0|\\+27)[1234][123][-| ]+"
    			"[0-9]{3}[-| ]+([0-9]{4})$");
    		return regex_match(lndln, e);
    	}
    
    	// Validate RSA cell/toll-free number 
    	bool cellNoValidator(const std::string& cn)
    	{
    		static const boost::regex e("(0|\\+27)[78]([01234]|[68])[-| ]+"
    			"[0-9]{3}[-| ]+([0-9]{4})$");
    		return regex_match(cn, e);
    	}
    
    	// Validate string not containing numbers 
    	bool stringValidator(const std::string& s)
    	{
    	   static const boost::regex e("^[a-zA-Z ]+$");
    	   return regex_match(s, e);
    	}
    
    	// Validate string containing numbers 
    	bool mixedStringValidator(const std::string& s)
    	{
    	   static const boost::regex e("^[a-zA-Z0-9  ]+$");
    	   return regex_match(s, e);
    	}
    
    	// Validate RSA postal code 
    	bool postalCodeValidator(const std::string& c)
    	{
    		static const boost::regex e("^([0-9]{4})$");
    		return regex_match(c, e);
    	}
    
    	// Validate RSA char/digit value
    	int charValidator(const char& c)
    	{
    		return isdigit(c); 
    	}
    
    	// Validate the rental type
    	int rentalTypeValidator(const std::string& s)
    	{
    		return !( s.compare("Unlimited") && s.compare("200km") );
    	}
    }

  9. #9
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by csonx_p View Post
    And this?
    Reason i asked this question is you saying "since they are templates", so does that mean if its not a template then i shouldn't make a namespace a .h file ?

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Header files typically contain namespaces and class declarations; you can always identify header files through the .h or .hpp suffix. However, templates are somewhat special in that template classes cannot be separated from their declarations. There are some hacks around that limitation, though you'll have to read to find out what they are, and it's not always worth the effort to do that.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Reason i asked this question is you saying "since they are templates", so does that mean if its not a template then i shouldn't make a namespace a .h file ?
    A namespace is a namespace, not a file. Likewise, a class is a class, not a file, and a template is a template, not a file.

    Typically, we would place a class definition in a header file and then place the class implementation in a source file. In the case of templates, we would typically just use header files. A namespace can be closed and then re-opened; it is just a way of grouping names. Consequently, you might place the definition of a class within a namespace in a header file, or place the declaration of a free function within a namespace in a header file.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    ...

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I think the confusion about namespaces and header files come from the common statement of "do not put using namespace XXX" in a header file. Which you shouldn't.

    If for some reason you want use namespaces for a particular group of functions, variables, type declaraions or constants, then you put "namespace somename" around the those things. If you have another group of things you want in another namespace, then you put another namespace around those. As many as you think makes sense. Commonly, you wouldn't put more than one namespace group in one header file, but there's nothing saying you CAN NOT do that.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    Registered User
    Join Date
    Apr 2008
    Posts
    610
    Quote Originally Posted by matsp View Post
    I think the confusion about namespaces and header files come from the common statement of "do not put using namespace XXX" in a header file. Which you shouldn't.

    If for some reason you want use namespaces for a particular group of functions, variables, type declaraions or constants, then you put "namespace somename" around the those things. If you have another group of things you want in another namespace, then you put another namespace around those. As many as you think makes sense. Commonly, you wouldn't put more than one namespace group in one header file, but there's nothing saying you CAN NOT do that.

    --
    Mats
    I'm having problems linking this namespace

    Code:
    #ifndef VALID_H
    #define VALID_H
    
    #include <boost/regex.hpp>
    #include <string>
    #include <time.h>
    
    #define YR_OLD 2
    
    namespace valid
    {
    	/* Validate RSA ID number */
    	bool driverIDValidator(const std::string& id)
    	{
    		static const boost::regex e("^[0-9]{6}[0-9]{4}[0-9]{3}$");
    		return regex_match(id, e);
    	}
    
    	// Validate RSA land line number 
    	bool landLineValidator(const std::string& lndln)
    	{
    		static const boost::regex e("(0|\\+27)[1234][123][-| ]+"
    			"[0-9]{3}[-| ]+([0-9]{4})$");
    		return regex_match(lndln, e);
    	}
    
    	// Validate RSA cell/toll-free number 
    	bool cellNoValidator(const std::string& cn)
    	{
    		static const boost::regex e("(0|\\+27)[78]([01234]|[68])[-| ]+"
    			"[0-9]{3}[-| ]+([0-9]{4})$");
    		return regex_match(cn, e);
    	}
    
    	// Validate string not containing numbers 
    	bool stringValidator(const std::string& s)
    	{
    	   static const boost::regex e("^[a-zA-Z ]+$");
    	   return regex_match(s, e);
    	}
    
    	// Validate string containing numbers 
    	bool mixedStringValidator(const std::string& s)
    	{
    	   static const boost::regex e("^[a-zA-Z0-9  ]+$");
    	   return regex_match(s, e);
    	}
    
    	// Validate RSA postal code 
    	bool postalCodeValidator(const std::string& c)
    	{
    		static const boost::regex e("^([0-9]{4})$");
    		return regex_match(c, e);
    	}
    
    	// Validate car engine size 
    	bool engineCapValidator(const std::string& c)
    	{
    		static const boost::regex e("^[0-9]{2}(00)$");
    		return regex_match(c, e);
    	}
    
    	// Validate RSA char/digit value
    	int charValidator(const char& c)
    	{
    		return isdigit(c); 
    	}
    
    	int rentalTypeValidator(const std::string& s)
    	{
    		return !( s.compare("Unlimited") && s.compare("200km") );
    	}
    	
    	bool yearModelValidator(const int& value)
    	{
    		time_t rawtime;
    		tm* timeinfo;
    
    		time( &rawtime );
    		timeinfo = localtime ( &rawtime );
    
    		int year = timeinfo->tm_year+1900;
    
    		if(value < year-YR_OLD && value > year)
    			return false;
    		else
    			return true;
    	}
    }
    
    #endif
    Used here ...

    Code:
    #include "Validator.h"
    
    void Fleet::ReadCarData(Car& car)
    {
    	string make, model, regNo;
    	char engineSize[10];
    	int ymodel;
    	Car::TankStatus ts;
    
    	do
    	{
    		cout << "\n\nEnter car make : ";
    		cin >> make; 
    	}
    	while ( !valid::mixedStringValidator(make) );
    
    	do
    	{
    		cout << "\nEnter car model : ";	
    		cin >> model;
    	}
    	while ( !valid::mixedStringValidator(model) );
    
    	do
    	{
    		cout << "\nEnter car registration number : ";
    		cin >> regNo;
    	}
    	while ( !valid::mixedStringValidator(regNo) );
    
    	do
    	{
    		cout << "\nEnter the year model of the car : ";
    		cin >> ymodel;
    	}
    	while ( !valid::yearModelValidator(ymodel) );
    
    	do
    	{
    		cout << "\nEnter the engine capacity : ";
    		cin >> engineSize;
    
    	}
    	while ( !valid::engineCapValidator(engineSize) );
    
    	do
    	{
    		cout << "\nTank Status [unknown=0, empty=1, half=2, full=3] :";
    		cin >> ts;
    	}
    	while( !(ts==Car::unknown || ts==Car::empty || ts==Car::full || ts==Car::half ) );
    
    	// Ensure correct tank details
    	if ( (ts>3) || (ts<0) ) {
    		ts=Car::unknown;
    	}
    	car.setCarDetails(make, model, regNo, ymodel, atoi(engineSize), ts);
    }
    Link Errors

    Code:
    1>Rental.obj : error LNK2005: "bool __cdecl valid::driverIDValidator(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?driverIDValidator@valid@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Fleet.obj
    1>Rental.obj : error LNK2005: "bool __cdecl valid::landLineValidator(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?landLineValidator@valid@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Fleet.obj
    1>Rental.obj : error LNK2005: "bool __cdecl valid::cellNoValidator(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?cellNoValidator@valid@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Fleet.obj
    1>Rental.obj : error LNK2005: "bool __cdecl valid::stringValidator(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?stringValidator@valid@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Fleet.obj
    1>Rental.obj : error LNK2005: "bool __cdecl valid::mixedStringValidator(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?mixedStringValidator@valid@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Fleet.obj
    1>Rental.obj : error LNK2005: "bool __cdecl valid::postalCodeValidator(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?postalCodeValidator@valid@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Fleet.obj
    1>Rental.obj : error LNK2005: "bool __cdecl valid::engineCapValidator(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?engineCapValidator@valid@@YA_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Fleet.obj
    1>Rental.obj : error LNK2005: "int __cdecl valid::charValidator(char const &)" (?charValidator@valid@@YAHABD@Z) already defined in Fleet.obj
    1>Rental.obj : error LNK2005: "int __cdecl valid::rentalTypeValidator(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?rentalTypeValidator@valid@@YAHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Fleet.obj
    1>Rental.obj : error LNK2005: "bool __cdecl valid::yearModelValidator(int const &)" (?yearModelValidator@valid@@YA_NABH@Z) already defined in Fleet.obj
    1>c:\C++ Folder\Rental Project\Fleet\Debug\Fleet.exe : fatal error LNK1169: one or more multiply defined symbols found
    Rental.CPP also includes "Validator.h" ... I think the conflict is there? How do i resolved this?

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Ah, yes. If a function is not a template or inline, it probably (as in, with very few exceptions) should go in a .cpp file. In this case, I don't see any reason why they should NOT be declared in valid.h, and then implemented in valid.cpp.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  2. Creating a database
    By Shamino in forum Game Programming
    Replies: 19
    Last Post: 06-10-2007, 01:09 PM
  3. Mmk, I give up, lets try your way. (Resource Management)
    By Shamino in forum Game Programming
    Replies: 31
    Last Post: 01-18-2006, 09:54 AM
  4. class errors
    By romeoz in forum C++ Programming
    Replies: 3
    Last Post: 09-16-2003, 07:57 PM