CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Dec 2003
    Posts
    30

    Unhappy completely a newbie question - about cpp/hpp files

    As I started to use C++ this tuesday, I did not know anything about it. For now, I tought I should do all the code like:

    Code:
    // file: Foo.cpp
    #ifndef INCLUDED_FOO
    #define INCLUDED_FOO
    
    #include <string>
    using namespace std;
    
    class Foo
    {
    private:
      string s;
    public:
    
      virtual ~Foo() {}
     
      virtual void print()
      {
        cout<<"foo";
      }
    
    };
    #endif
    
    --------
    
    // file: Bar.cpp
    #ifndef INCLUDED_BAR
    #define INCLUDED_BAR
    
    #include <string>
    using namespace std;
    #include "Foo.cpp"
    
    
    class Bar : public Foo
    {
    private:
      string g;
    
    public:
      virtual ~Bar() {}
    
      void print()
      {
        cout<<"bar";
      }
    };
    #endif

    ok, I realized that I have to split the code into hpp and cpp files.
    Well I tried the following, but the gcc compiler prompts about

    virtual outside class declaration...


    Code:
    // foo.hpp
    
    #ifndef INCLUDED_FOO_HPP
    #define INCLUDED_FOO_HPP
    
    class Foo
    {
    private:
      string s;
    public:
      virtual ~Foo() {}
      virtual void print();
    };
    #endif
    
    -----
    
    // foo.cpp
    
    #include <string>
    
    using namespace std;
    
    #include "Foo.hpp"
    
    virtual Employee::~Employee() {}
    
    virtual void Employee::print()
    {
      cout<<"foo";
    }

    What I`m missing here?

  2. #2
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582
    You cannot put "virtual" in the .cpp file. Remove it and it should compile.

    Also, never put "using namespace <anything>" in a header file. It forces everybody that includes that file to use that namespace.

    Jeff

  3. #3
    Join Date
    Sep 2002
    Posts
    1,747
    You're not missing... you've added something. The "virtual" keyword only gets placed inside the class declaration (the part that gets put in the header). The implementation of the various function definitions do not need (nor can they, according to the language) to tell the compiler anything about it being virtual (since that translation unit already knows by including the header and all other translation units have that same information so they can compile for dynamic binding).
    */*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/

    "It's hard to believe in something you don't understand." -- the sidhi X-files episode

    galathaea: prankster, fablist, magician, liar

  4. #4
    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    762
    Don't include c, cc, or cpp files EVER.

    Don't do it.

  5. #5
    Join Date
    Dec 2003
    Posts
    30
    Hi again,

    I tried, but no luck

    Code:
    #ifndef INCLUDED_ANIMAL_HPP
    #define INCLUDED_ANIMAL_HPP
    
    
    class Animal  
    {
    protected:
    
    	string name;
    
    	string colour;
    			
    	string breed;	
    
    public:
    	// virtual destructor to make derived classes virtual
    	virtual ~Animal() {}
    
    	virtual void setName(string nam);
    
    	virtual string getName();
    
    	virtual void setColour(string c);
    
    	virtual string getColour();
    	// help function
    	virtual void clearBuffer(char chars[] ,int len);
    
    	virtual void setBreed(string g) = 0;
    
    	virtual string getBreed() = 0;
    
    	virtual void serialize(ofstream& file) = 0;
    
    	virtual void deSerialize(ifstream& file) = 0;
    };
    #endif
    Code:
    #include <string>
    #include <fstream>
    
    using namespace std;
    
    #include <string>
    #include "Animal.hpp"
    
    Animal::~Animal() {}
    
    void Animal::setName(string name)
    {
    	name = nam;
    }
    
    string Animal::getName()
    {
    	return name;
    }
    
    void Animal::setColour(string c)
    {
    	colour = c;
    }
    
    string Animal::getColour()
    {
    	return colour;
    }
    
    void Animal::clearBuffer(char chars[] ,int len)
    {
    	for(int i = 0; i < len; i++)
    		chars[i] = ' ';
    }
    
    void Animal::setBreed(string b) = 0;
    
    string Animal::getBreed() = 0;
    
    void Animal::serialize(ofstream& file) = 0;
    
    void Animal::deSerialize(ifstream& file) = 0;
    The output when I compile:

    Code:
    C:\projects\animal>gcc -c -Wall Animal.cpp
    Animal.cpp:13: redefinition of `Animal::~Animal()'
    Animal.hpp:18: `virtual Animal::~Animal()' previously defined here
    Animal.cpp: In member function `virtual void
       Animal::setName(std::basic_string<char, std::char_traits<char>,
       std::allocator<char> >)':
    Animal.cpp:17: `nam' undeclared (first use this function)
    Animal.cpp:17: (Each undeclared identifier is reported only once for each
       function it appears in.)
    Animal.cpp: At global scope:
    Animal.cpp:41: function `virtual void Animal::setBreed(std::basic_string<char,
       std::char_traits<char>, std::allocator<char> >)' is initialized like a
       variable
    Animal.cpp:41: declaration of `virtual void
       Animal::setBreed(std::basic_string<char, std::char_traits<char>,
       std::allocator<char> >)' outside of class is not definition
    Animal.cpp:43: function `virtual std::string Animal::getBreed()' is initialized
       like a variable
    Animal.cpp:43: declaration of `virtual std::string Animal::getBreed()' outside
       of class is not definition
    Animal.cpp:45: function `virtual void Animal::serialize(std::ofstream&)' is
       initialized like a variable
    Animal.cpp:45: declaration of `virtual void Animal::serialize(std::ofstream&)'
       outside of class is not definition
    Animal.cpp:47: function `virtual void Animal::deSerialize(std::ifstream&)' is
       initialized like a variable
    Animal.cpp:47: declaration of `virtual void
       Animal::deSerialize(std::ifstream&)' outside of class is not definition

    ...not a clue ....

  6. #6
    Join Date
    Mar 2002
    Location
    California
    Posts
    1,582
    You are providing a body more than once.

    In the header, instead of:
    Code:
    virtual ~Animal() {}
    you should have

    Code:
    virtual ~Animal();
    Jeff

  7. #7
    Join Date
    Dec 2003
    Posts
    30
    virtual ~Animal();
    ah, one error message removed!

    But it did not affect to the rest...

  8. #8
    Join Date
    Dec 2003
    Posts
    30
    ah, got it!

    Those virtual functios should not be in the cpp file ... works fine!

    Thanks again !!

  9. #9
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,721
    In your Animal class, you made EVERY function virtual,
    even the "get" and "set" functions (setName(),getName() etc.)

    I don't think that you really want those functions redefinable
    in derived classes, so I would make them non-virtual. Of
    course, if you do want them to be redefianble in derived
    classes, then keep them virtual.

    Also, look at the argugment in your setName() (and oher set
    functions). It is "string nam". You are passing the string
    variable by value, which causes a copy to be made. This
    can be somewhat inefficent. For these types of functions,
    you should pass by const reference. This makes it so
    a copy does not have to be made, but still prevents
    the function from modifying the argument.

    Code:
    void Animal::setName(const string& name) // change in header also
    {
    //...
    }
    Last edited by Philip Nicoletti; December 5th, 2003 at 05:18 PM.

  10. #10
    Join Date
    Oct 2000
    Location
    London, England
    Posts
    4,773
    I see a lot of errors, some of which have been addressed.

    Basically, class declarations go into a .hpp file (or .h or .hxx)

    The body code of a class goes into a .cpp file (or .cxx)

    The exception is templates, where everything must go into one file.

    In addition, there are occasions where you will inline all the code of a class within its header file, and there are other classes which may occasionally be defined within a source file, particularly functor classes when you get advanced enough to use them.

    But best to stick for now with the rule of .hpp files showing class prototypes only.

    One thing you should become accustomed to (best to start with good habits) is to pass const string & as parameters rather than string. Passing as a string parameter works but is less efficient.

  11. #11
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    Hi NMTop40, long time no see.

    A general rule for splitting between header and implementation files:

    The header file contains only what you want the rest of the program to know about. The implementation file contains everything else.

    Corollary: give the rest of the program the minimum amount of information necessary to use your class.

    Sometimes, of course, you have to give more away (template classes for example), but in general your attitude should be to hide as much as possible - that way, changes that you make to your implementation have less efect on the rest of the program.

    Look up the pimpl idiom for a prime example of hiding implementation.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured