Закрытый вложенный абстрактный класс C ++ - PullRequest
7 голосов
/ 16 февраля 2011

Так что, возможно, это глупый вопрос, и я слишком обдумываю это, но у меня следующая ситуация. Я делаю «класс Shell», который может запускать абстрактные объекты «класс действий». Это единственный класс, который должен создавать или использовать эти объекты. Объекты действий нуждаются в доступе к командной консоли для выполнения определенных действий над ней, но я стараюсь избегать добавления общедоступных интерфейсов для этого (никто другой не должен этого делать).

У меня изначально был простой (не такой элегантный)

class Shell
{
 public:
    bool checkThing();
    // etc...
 private:
    bool _thing;
};

class Action
{
 public:
    virtual void execute( Shell &s )=0;
};

class ChangeAction : public Action
{
 public:
    void execute( Shell &s )
    {
        // requires friendship or public mutator!
        s._thing = true;
    }
};

Итак, я рассмотрел вложенный класс Action, но я хотел сделать его закрытым (зачем кому-то еще делать конкретные действия, кроме Shell, верно?)

class Shell
{
 public:
    bool checkThing();
    // etc...
 private:
    bool _thing;
    class Action;
};

class Shell::Action
{
 public:
    virtual void execute( Shell &s )=0;
};

class ChangeAction : public Shell::Action
{
 public:
    void execute( Shell &s )
    {
        // ok now!
        s._thing = true;
    }
};

Но, конечно, я больше не могу наследовать от Action (это имеет смысл, это личное). Так что это не работает.

Итак, мой вопрос, я должен просто пойти с первым методом и дружбой или публичным интерфейсом? Могу ли я использовать что-то похожее на второй метод, чтобы сохранить эту связь с действиями и оболочкой? У тебя есть идея получше?

Ответы [ 2 ]

3 голосов
/ 16 февраля 2011

Если единственный код, который должен быть в состоянии видеть Action, это Shell, то одним из вариантов будет прямое объявление Action в заголовочном файле, но только определение класса в файле .cpp.Тогда это позволит вам объявить столько Action подклассов, сколько вы хотите в файле реализации, не позволяя никому другому подклассу выходить за пределы Action, потому что никто не будет иметь полного определения класса для Action.Это также устраняет необходимость в общедоступных интерфейсах или объявлениях friend - все классы Action объявлены в глобальной области видимости, но экранированы от других файлов благодаря объявлению в файле .cpp.

Отличновопрос, кстати!

0 голосов
/ 16 февраля 2011

Вы можете использовать комбинацию методов: в основном просто возьмите все ваши классы из первого метода и переместите их в приватный раздел класса Shell:

class Shell {
public:
    bool checkThing();     // etc...
private:
    bool _thing;

    class Action {
    public:
        virtual void execute( Shell &s )=0;
    };

    class ChangeAction : public Action
    {
    public:
        void execute( Shell &s )
        {
            // ok now!         s._thing = true;
        }
    }; 

};
...