C++ C++;私有嵌套抽象类

C++ C++;私有嵌套抽象类,c++,inheritance,friend,nested-class,C++,Inheritance,Friend,Nested Class,也许这是个愚蠢的问题,我想得太多了,但我有以下情况。我正在制作一个“类外壳”,它可以运行抽象的“类动作”对象。它是唯一应该创建或使用这些对象的类。Action对象需要访问Shell才能对其执行特定的操作,但我试图避免为此添加公共接口(不允许其他人这样做) 我原来有一个简单的(不那么优雅) 所以我考虑了一个嵌套的类操作,但我想将其私有化(为什么除了Shell,其他人都可以做具体的操作,对吗?) 但我当然不能再从行动中继承(这是有道理的,它是私人的)。所以这不起作用 所以我的问题是,我应该使用第一种

也许这是个愚蠢的问题,我想得太多了,但我有以下情况。我正在制作一个“类外壳”,它可以运行抽象的“类动作”对象。它是唯一应该创建或使用这些对象的类。Action对象需要访问Shell才能对其执行特定的操作,但我试图避免为此添加公共接口(不允许其他人这样做)

我原来有一个简单的(不那么优雅)

所以我考虑了一个嵌套的类操作,但我想将其私有化(为什么除了Shell,其他人都可以做具体的操作,对吗?)

但我当然不能再从行动中继承(这是有道理的,它是私人的)。所以这不起作用

所以我的问题是,我应该使用第一种方法和友谊,还是使用公共界面?我可以使用类似于第二种方法的方法来保持与动作和Shell的关系吗?
您有更好的主意吗?

如果需要查看
操作的唯一代码是
Shell
,一个选项是在头文件中向前声明
操作,但只在.cpp文件中定义类。这将允许您在实现文件中声明任意多的
Action
子类,而不允许任何其他人从
Action
中派生子类,因为没有其他人会拥有
Action
的完整类定义。这也避免了对公共接口或
friend
声明的任何需要-所有
Action
类都在全局范围内声明,但由于在.cpp文件中声明,因此与其他文件隔离


顺便提一下,这个问题问得好

您可以使用以下方法的组合:基本上只需从第一个方法中获取所有类,并将它们移动到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;
        }
    }; 

};

如果Shell需要创建具体的动作类呢?使用这个方法,Shell不知道具体的类,所以看起来我需要一个工厂。但那属于哪里呢?起初我认为Shell会自己处理这个问题,但是我需要一个单独的工厂类吗?谢谢你的建议@Matt-如果所有操作都在.cpp文件中声明,并带有Shell代码,那么Shell应该能够直接实例化它们。如果您愿意,您也可以创建一个工厂,但是如果您这样做,那么也应该将其放入.cpp文件中。这样做的目的是将所有实现细节都保存在.cpp文件中,代码的其他部分无法看到它们。对不起,我以为我理解了这一点,但我有点困惑。
Action
是否仍然是
Shell
的嵌套类?你说我不需要让
Action
成为
Shell
的朋友,但是如何让
Action
的子类访问
Shell
的私有成员呢?@Matt-啊,如果Action需要查看Shell的私有内部,如果您不想向所有人公开类的内部内容,那么您必须让它成为朋友。我没有注意到这个要求。好的,谢谢,这看起来确实是个好方法。我一直在重新考虑为Action需要的东西添加一个公共接口,因为它们并没有完全违反封装,而是将它们公开,我有点喜欢它,而不是让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;
    }
};
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;
        }
    }; 

};