-1

I am trying to use nested classes instead of multiple inheritance. I am following the recommendations from the book but I keep getting an error in the constructor. Basically, Person is the grandfather, Student and Employee are the Parent and Teaching Assistant is the child. TeachingAssistant will have a nested class that will have reference to its outer class, but when I use the code from the book I get two errors

I get the error

Error 1 *"No matching constructor for Initialization of TeachingAssistant::EmployeePart"

and this error

Error 2 "Out of line definition of 'EmployeePart' does not match any declaration in 'TeachingAssistant::EmployeePart'"

Here is the code:

class TeachingAssistant : public Student
{
public:
    TeachingAssistant();
private:
    class EmployeePart;
    EmployeePart* employee_ptr;
};

class TeachingAssistant::EmployeePart : public Employee
{
public:
    EmployeePart(TeachingAssistant&);
private:
    TeachingAssistant* ta_part; // Allows access back to outer class
};

Error 1 is here in this constructor

TeachingAssistant::TeachingAssistant()
{
    employee_ptr = new EmployeePart(this); // Pass pointer to implicit parameter
}

Error 2 is here

TeachingAssistant::EmployeePart::EmployeePart(TeachingAssistant* taval)
: ta_part(taval) {}

Why do these errors pop up if I am providing the constructors?

6
  • 1
    (TeachingAssistant* taval) is not the same signature as in the declaration EmployeePart(TeachingAssistant&);. Commented Jan 12, 2016 at 9:16
  • Have you tried to define default constructure EmployeePart() to fix error 1? Commented Jan 12, 2016 at 9:21
  • I still get the error if I use the default constructor Commented Jan 12, 2016 at 9:28
  • You must pass a reference not a pointer so, new EmployeePart(*this) or change the prototype to EmployeePart(TeachingAssistant *) Commented Jan 12, 2016 at 9:32
  • Second error, is that EmployeePart is not a nested class: you did'nt declared or defined it inside TeachingAssistant. Either define/declare it inside or remove the prefix TeachingAssistant:: Commented Jan 12, 2016 at 9:34

2 Answers 2

1

Your basic problem is that you have called the EmployeePart constructor wrongly, and defined it wrongly. However, while we are fixing that, we will also address the fact that you should prefer to not use new, and not to use raw pointers that own memory, and not to use pointers when you don't need nullability or reseatability.

class TeachingAssistant : public Student
{
public:
    TeachingAssistant();
    TeachingAssistant(const TeachingAssistant&rhs) = delete;   // Delete copy constructor.
    TeachingAssistant& operator=(const TeachingAssistant&rhs) = delete; // And assignment.
private:
    class EmployeePart;
    std::unique_ptr<EmployeePart> employee_ptr;    // First change here.
};

class TeachingAssistant::EmployeePart : public Employee
{
public:
    EmployeePart(TeachingAssistant&);    
private:
                                // Second change here.  Store reference, not pointer.
    TeachingAssistant& ta_part; // Allows access back to outer class
};

Create the employee_ptr in the initialization list, and pass *this, not this.

TeachingAssistant::TeachingAssistant()
  : employee_ptr(std::make_unique<EmployeePart>(*this))  // Pass reference to constructor
{
}

Fourth change is on next line:

TeachingAssistant::EmployeePart::EmployeePart(TeachingAssistant& taval)
: ta_part(taval) {}
7
  • If you use a raw pointer for employee_ptr, you have to worry about a destructor (to free the memory), and copy constructors (you don't want to pointers pointing at the same block, if their destructors are both going to free it), and similarly for copy assignment. If you use unique_ptr, destructor and move constructor/assigment "just work" and copy constructor/assignment won't compile until you write a specialization. Commented Jan 12, 2016 at 10:02
  • Using a pointer for ta_part is less problematic, but given that you never want to be able to change the address of the TA which owns this employee_part, and you never want it to be null, a reference better matches the semantics. Commented Jan 12, 2016 at 10:04
  • I lied. move constructor/assignment won't work - they will compile, but they will be wrong. (The ta_part will be a dead reference to the source object.) Commented Jan 12, 2016 at 10:05
  • So basically unique_ptr handles the memory management and the big 3? Does auto_ptr work the same as unique_ptr? Commented Jan 12, 2016 at 10:07
  • So if I use a unique_ptr the constructor and assignment compile but do not work correctly? Commented Jan 12, 2016 at 10:08
0
EmployeePart(TeachingAssistant&);

Your constructor wants reference, but you are passing this with is pointer employee_ptr = new EmployeePart(this); pass *this instead

Second error. Your declaration is different than definition. See TeachingAssistant* taval and EmployeePart(TeachingAssistant&);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.