passing One class as input to another class that takes multiple reference interfaces for his constructor C++

Viewed 56

I have Manager class that inherit multiple interfaces and implements them.

class iperson
{
    public:
    virtual void doSomething1() = 0;
};

class imachine
{
    public:
    virtual void doSomething2() = 0;
};

class ibook
{
    public:
    virtual void doSomething3() = 0;
};

class Manager: iperson, imachine, ibook
{
    public:
    void doSomething1() override 
    {/** implemetation **/}
    
    void doSomething2() override
    {/** implemetation **/}
    
    void doSomething3() override
    {/** implemetation **/}

    /*** 
    another code and implemetation 
    ****/
}; 

And there is Employee class that takes Manager implementation as input for its constructor

class Employee
{
    Employee(iperson& person, imachine& machine, ibook& book)
    { /*** some code ***/ }
};

And when i need to pass Manger to Employee from Manager class, I end up with code like this

/** That looks bad passing three this XD **/
Employee employee(*this, *this, *this);

Why using interfaces instead of passing Manager reference?(what i'm trying to achieve) 1- to be able to mock these methods while testing the employee class 2- to restrict access of employee classes to just these methods, not all Manager methods

So the question is: is there better solution instead of passing the three (*this) pointer?

2 Answers

Yes. (There is a better way).

Consider the way you wrote your inheritance (I don't know if that was intentional):

class IManager: iperson, imachine, ibook

(instead of:

class IManager: public iperson, public imachine, public ibook

If your use of private inheritance is intentional in your example, write your manager as:

class IManager: 
    private iperson, 
    private imachine,
    private ibook
{
    // add these:
    iperson& as_person() { return *this; }
    imachine& as_machine() { return *this; }
    ibook& as_book() { return *this; }
};

This disconnects the fact that your imanager is a person from the requirement to procide a person to client code.

In the future you may want to change it to (for example):

class IManager: 
    private imachine,
    private ibook
{
    // add these:
    virtual iperson& as_person() = 0;
    imachine& as_machine() { return *this; }
    ibook& as_book() { return *this; }
};

class ConcreteManager: public IManager
{
    iperson& as_person() override
    {
        person_facade = PersonForManager(*this);
        return person_facade;
    }

private:
    person_facade * person; // no longer written as inheritance
}

Since you use methods for the different aspects of your interface, you can change them in a single place.

How about

class IManager: iperson, imachine, ibook
{
} 

class Manager :IManager
{

    public:
    void doSomething1() override 
    {/** implemetation **/}
    
    void doSomething2() override
    {/** implemetation **/}
    
    void doSomething3() override
    {/** implemetation **/}

    /*** 
    another code and implemetation 
    ****/
} 

then you can do

class MockManager: IManager
{
    public:
    void doSomething1() override 
    {/** implemetation **/}
    
    void doSomething2() override
    {/** implemetation **/}
    
    void doSomething3() override
    {/** implemetation **/}

    /*** 
    another code and implemetation 
    ****/
} 

and

class Employee
{
    Employee(IManager &man)
    { /*** some code ***/ }
}
Related