Findus
Findus

Reputation: 313

C++ decorator: Access public function of base class from outside

I want to try the use of C++ decorators and I have some questions.

Using this example: https://gist.github.com/dlivingstone/3006324#file-decoratormain-cpp

class AbstractNPC {
public:
    virtual void render() = 0;
};

class NPC: public AbstractNPC {
public:
    NPC() { }
    render(){...}
};

class NPCDecorator: public AbstractNPC {
private:
    AbstractNPC * npc;
public:
    NPCDecorator(AbstractNPC *n) { npc = n; }
    void render() { npc->render(); } // delegate render to npc data member
};

class Elite: public NPCDecorator {
public:
    Elite(AbstractNPC *n): NPCDecorator(n) { }
    void render() {
        cout << "Elite "; // render special features
        NPCDecorator::render(); // delegate to base class
    }
};

int main(){
    AbstractNPC *goblin1= new Elite(new Shaman(new NPC("Goblin")));
    ...
}

Do I have to to make each function virtual in AbstractNPC and redirect it from NPCDecorator to call it from outside?

class NPC: public AbstractNPC {
public:
    NPC();
    void render() {...}
    void func1() {...}
    void func2() {...}
    void func3() {...}
    void func4() {...}
    void func5() {...}
};
int main(){
    AbstractNPC *goblin1= new Elite(new Shaman(new NPC("Goblin")));
    call func1(); ???
}

Upvotes: 0

Views: 172

Answers (1)

aschepler
aschepler

Reputation: 72421

Class NPC here should be a concrete class with real implementations of all virtual functions. It can be the minimum simple NPC, where the implementations are the basic logic which should be used if no decorators at all are applied. Notice it doesn't even have a pointer member to redirect to.

Class NPCDecorator should have functions redirecting all public interface virtual calls to its npc pointer member.

Specific decorators like Elite and Shaman only need to define the virtual functions where they change the behavior. If Elite has no effect on what func2 does, it can skip declaring and defining func2 entirely, since it will be visible from base class NPCDecorator.

I would definitely change all pointers to std::unique_ptr and all new expressions to std::make_unique here, to avoid writing manual cleanup code and the potential for plenty of bugs and headache.

Upvotes: 2

Related Questions