C ++: expected class name before '{' token

When I try to run this code:

Instructor.cpp:

#include "Instructor.h" #include "Person.h" using std::string; Instructor::Instructor() { Person(); salary = 0; } Instructor::Instructor(string n, string d, string g, int s) { Person(n, d, g); salary = s; } void Instructor::print() { if (gender == "M") std::cout << "Mr. "; else std::cout << "Ms. "; Person::print(); std::cout << " Instructor, Salary: " << salary << std::endl; } 

Instructor.h:

 #include <iostream> #include <string> class Instructor: public Person { public: Instructor(); Instructor(std::string n, std::string d, std::string g, int s); virtual void print(); protected: int salary; }; 

Person.h:

 #include <iostream> #include <string> class Person { public: Person(); Person(std::string n, std::string d, std::string g); virtual void print(); protected: std::string name; std::string dob; std::string gender; }; 

I get the following errors:

 In file included from Instructor.cpp:1:0: Instructor.h:5:1: error: expected class-name before '{' token { ^ Instructor.cpp: In member function 'virtual void Instructor::print()': Instructor.cpp:16:6: error: 'gender' was not declared in this scope if (gender == "M") ^ Instructor.cpp:20:16: error: cannot call member function 'virtual void Person::print()' without object Person::print(); 

All three errors confuse me. If the instructor class was obtained from Person and inside the gender field gender, then why do I get error: 'gender' was not declared in this scope , as well as error: cannot call member function 'virtual void Person::print()' without object ?

It seems to me that I am doing something obviously wrong here, for example, including files incorrectly or something like that. Any help is appreciated.

+8
c ++ netbeans
source share
5 answers

You must include person.h in instructor.h , otherwise the Person token is unknown to the compiler. And when you do this, make sure you remove person.h from instructor.cpp . Otherwise, you will receive a re-declaration error. But it’s common practice to use #ifdef directives in header files to prevent multiple inclusion. as in person.h

 #ifndef PERSON_H #define PERSON_H /// class definition and other code #endif //PERSON_H 

or you can use #pragma once in VC ++.

Another mistake is that you are not initializing the Person part of the Instructor correctly. In the constructor:

 Instructor::Instructor(string n, string d, string g, int s) { Person(n, d, g); // this will create a temporary `Person` object instead of initializing base part and // default constructor of `Person` will be used for this `Instructor` object salary = s; } 

do it like that

 Instructor::Instructor(string n, string d, string g, int s): Person(n,d,g), salary(s) { } 
+8
source share

A few questions:

  • At the time you defined your Instructor class, your Person class is not yet defined. You must #include "Person.h" at the beginning of Instructor.h , which will lead to the second problem ...
  • Your headers are not protected against double inclusion (this is the error you see in your comment above). To fix this, you will need an include defender:

     #ifndef PERSON_H #define PERSON_H class Person { // ... }; #endif 

    The second time this file is included, PERSON_H already defined, so that between #ifndef and #endif will be ignored.

  • You are not calling the base class constructor correctly. The correct syntax is:

     Instructor::Instructor(string n, string d, string g, int s) : Person(n, d, g){ salary = s; } 

    What you do (writing Person(n, d, g); to the constructor body) will be compiled, because if you do not explicitly call the base class constructor, the compiler will try to call the default constructor without parameters for you, and in your case, Person has a default constructor that can be called (if Person does not have a constructor that does not accept any parameters, you will get a compilation error). However, the effect of this statement is to simply create a temporary Person object, which is destroyed at the end of the statement rather than calling the base class constructor.

    This syntax (called a member initialization list) can also be used to initialize other members of the class and is actually the preferred way:

     Instructor::Instructor(string n, string d, string g, int s) : Person(n, d, g), salary(s) { } 
+2
source share

Each time the compiler encounters the #include "FileName.h" directive of the preprocessor, the compiler tries to reload - and, I suppose, override - the included class. This will result in a compile time error. Learn more about include guard> or the #ifndef wrapper here .

To "guard" against this, we use include guard - which should appear before any of your code in your header file.

For example:

 #ifndef CLASSIDENTIFIER_H // Capitalized letters are convention (see below) #define CLASSIDENTIFIER_H #include <iostream> #include <cstdlib> public ClassIdentifier { // Class Member Declarations }; #endif 

#ifndef means if not defined. The following identifier - in all capitals without any reason other than β€œhow it is done” - is also called by convention according to the class name (this allows the compiler to check a number of things, first of all ensuring that - if everyone follows the agreement - that no other class with the same name was included, specified or defined in the program.

Logically, we can conclude that the next two include guards , designate "define" and "end if not defined".

If you included your #endif right after closing your class declaration, for example. };#endif (see above), this will also lead to a compile-time error, and this may not be entirely obvious (although, I think, the compiler is pretty clear with the appearance of its error message).

The other code that I included is, of course, just for the sake of acquaintance and demonstration of what is possible.

+1
source share

Several things need to be fixed:

  • Instructor.h must have #include "Person.h" . He is needed there, so Instructor understands what he inherits. There is no need for this to exist in Instructor.cpp if you move it to Instructor.h since Instructor.cpp has Instructor.h .
  • I'm not sure if you want Person be an abstract base class, but I don't see Person.cpp or any implementation of any member functions in Person.h . Even if you want Person be an abstract base class, you need to provide the function body to the constructor, even if it is empty.

    Person() {};

  • You call Person::print in Instructor::print with no implementation.

  • When using inheritance, you need to use the member initialization list, which calls the base class constructor to initialize the member variables of the base class. In both instructor constructors, using the Person constructors in the function body, as you are now, does not produce the desired result.
    Moreover, the use of initialization lists is a more efficient and accepted convection for setting your own class member variables.

    Instructor::Instructor() : Person(), salary(0) { }

    Instructor::Instructor(string n, string d, string g, int s) : Person(n, d, g), salary(s) { }

0
source share

Isn't that just the procedure for including header files in Instructor.cpp? First you will need to include Person.h and then Instructor.h. Thats it.

-one
source share

All Articles