-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?

user2076774
  • 405
  • 1
  • 8
  • 21

2 Answers2

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) {}
  • 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. – Martin Bonner supports Monica Jan 12 '16 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. – Martin Bonner supports Monica Jan 12 '16 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.) – Martin Bonner supports Monica Jan 12 '16 at 10:05
  • So basically unique_ptr handles the memory management and the big 3? Does auto_ptr work the same as unique_ptr? – user2076774 Jan 12 '16 at 10:07
  • So if I use a unique_ptr the constructor and assignment compile but do not work correctly? – user2076774 Jan 12 '16 at 10:08
  • I have explicitly deleted the copy constructor/assignment. That will also delete the move operators. If you want them, that is going to be more complex. – Martin Bonner supports Monica Jan 12 '16 at 10:08
  • Auto_ptr was a failed attempt to write unique_ptr. It failed because C++ didn't have move operators at the time, and the big 3 are now the big 5. Constructor and assignment would indeed compile, but `this->employee_ptr->ta_part` would not be `this`. – Martin Bonner supports Monica Jan 12 '16 at 10:10
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&);

userbb
  • 2,148
  • 5
  • 30
  • 53