views:

137

answers:

5

Hi,

I am new to this website and I am trying a simple inheritance example in C++. I checked my code lots of times and I really see nothing wrong with it, however the compilers gives me errors:

my code:

#ifndef READWORDS_H
#define READWORDS_H
using namespace std;
#include "ReadWords.h"

/**
 * ReadPunctWords inherits ReadWords, so MUST define the function filter.
 * It chooses to override the default constructor.
 */

class ReadPunctWords: public ReadWords {
    public:
    bool filter(string word);
};

#endif

And the messages I get from the compiler:

ReadPunctWords.h:11: error: expected class-name before '{' token
ReadPunctWords.h:13: error: `string' has not been declared
ReadPunctWords.h:13: error: ISO C++ forbids declaration of `word' with no type

Tool completed with exit code 1

I am really not sure where I get it wrong as it looks just fine to me? Thank you for any mistakes you might spot.

+12  A: 

You need to include string:

#include <string>

That said, don't use using namespace! Especially at file-scope, and definitely not in a header file. Now any unit that includes this file is forced to succumb to everything in the std namespace.

Take that out, and qualify your names:

bool filter(std::string word);

It's arguable more readable, too. Additionally, you should take your string as a const&:

bool filter(const std::string& word);

To avoid having to copy the string unnecessarily. Lastly, your header guards seem off. Should they be changed? As of now, they seem like the same ones that would be used in your other header, which might effectively stop it from being included.

If you define READWORDS_H and then include ReadWords.h, and if that also has:

#ifndef READWORDS_H
#define READWORDS_H

Then nothing in that file will be processed. If that's the case, ReadWords as a class won't be defined, and you cannot inherit from it. Your guard should probably be:

READPUNCTWORDS_H
GMan
Thank you! I included that and I still get this error:ReadPunctWords.h:12: error: expected class-name before '{' tokenTool completed with exit code 1
Alex
Probably the header guards.
GMan
Excellent thank you!
Alex
No problem. Heed my advice about `using namespace`, if anything. :]
GMan
+2  A: 
interjay
Thank you, included the string and I still get this error:ReadPunctWords.h:12: error: expected class-name before '{' tokenTool completed with exit code 1
Alex
See my edit about include guards - ReadWords.h is probably not getting included.
interjay
A: 

also looks like something wrong with ReadWords class def (message for line 11)- we need to see .h file

aha - the sentinial def you use prevents the readwords.h include being read

you need

 #ifndef _READPUNCTWORDS_H
 #define _READPUNCTWORDS_H
pm100
He has no leading underscores, and those are reserved for the compiler anyway.
GMan
+1  A: 

This particular form of error is often caused by a type not being defined (at least when the code looks syntactically correct), in this case probably the class ReadWords but maybe also std::string.

You need to include to get std::string, as other posters have written, but also your guard

#ifndef READWORDS_H
#define READWORDS_H

almost certainly conflicts with the guard in ReadWords.h. You need to make sure your guards are distinct in different header files otherwise you will get conflicts like this. You should change the guard to something like

#ifndef READPUNCTWORDS_H
#define READPUNCTWORDS_H

// ...

#endif

In fact, it's better to have even more verbose guards to make sure they don't conflict. We use guards of the form

#ifndef MODULE_OR_PATH_FILE_H_INCLUDED
#define MODULE_OR_PATH_FILE_H_INCLUDED

// ...

#endif

This ensures different modules or libraries with similarly named headers don't conflict, the INCLUDED thing at the end is my own particular foible that makes the guard slightly more readable.

It's also bad practice to place a "using" declaration in a header file, because it places (potentially unwanted or conflicting) symbols in the global namespace everywhere you include the header. Personally, I prefer to retain the namespace for clarity or alias it in cpp files if it's a long one, for example

namespace fs = boost::filesystem;
Adam Bowen
Excellent! Thank you!
Alex
A: 

I also suspect the include guards. If they are named the same way in both header files, the result should be something like the following when ReadWords.h is pasted into ReadPunctWords.h.

#ifndef READWORDS_H // Is READWORDS_H defined? No, proceeding
#define READWORDS_H // Now it is defined

// Contents of ReadWords.h is pasted in here
#ifndef READWORDS_H // Is READWORDS_H defined? Yes, ignoring the contents of ReadWords.h (skipping til #endif)
#define READWORDS_H

class ReadWords { ... }; // This is never seen by the compiler as the preprocessor removed it

#endif

class ReadPunctWords: public ReadWords { // Error: ReadWords isn't declared...
public:
    bool filter(string word);
};

#endif
Anton