抽象类C ++中的变量

时间:2010-05-16 11:11:06

标签: c++ abstract-class

我有一个抽象类CommandPath,以及许多派生类,如下所示:

class CommandPath {
    public:
        virtual CommandResponse handleCommand(std::string) = 0;
        virtual CommandResponse execute() = 0;
        virtual ~CommandPath() {}
};

class GetTimeCommandPath : public CommandPath {
    int stage;
    public:
        GetTimeCommandPath() : stage(0) {}
        CommandResponse handleCommand(std::string);
        CommandResponse execute();
};

所有派生类都有成员变量'stage'。我想在所有这些中构建一个函数,它以相同的方式操纵'stage',所以我没有多次定义它,而是认为我将它构建到父类中。我将'stage'从所有派生类的私有部分移动到CommandPath的受保护部分,并添加了如下函数:

class CommandPath {
    protected:
        int stage;
    public:
        virtual CommandResponse handleCommand(std::string) = 0;
        virtual CommandResponse execute() = 0;
        std::string confirmCommand(std::string, int, int, std::string, std::string);
        virtual ~CommandPath() {}
};

class GetTimeCommandPath : public CommandPath {
    public:
        GetTimeCommandPath() : stage(0) {}
        CommandResponse handleCommand(std::string);
        CommandResponse execute();
};

现在我的编译器告诉我构造函数行没有派生类有成员'stage'。我的印象是受保护的成员对派生类是可见的吗?

构造函数在所有类中都是相同的,所以我想我可以将它移动到父类,但我更关心的是找出派生类无法访问变量的原因。

此外,由于之前我只使用了父类用于纯虚函数,我想确认这是添加一个要由所有派生类继承的函数的方法。

2 个答案:

答案 0 :(得分:14)

试试这个:

class CommandPath {
protected:
  int stage;
public:
  CommandPath(int stage_) : stage(stage_) {}
};

class GetTimeCommandPath : public CommandPath {
public:
  GetTimeCommandPath(int stage_) : CommandPath(stage_) {}
};

(为简洁省略了额外的代码)。

您不能在父类的成员上使用初始化列表,只能使用当前的成员。如果这是有道理的。

答案 1 :(得分:4)

首先:不要将protected用于属性。

这似乎是随意的,但关键在于它打破了封装。想象一下,当int完成时,你突然意识到使用unsigned short的空间是什么,所以你继续改变CommandPath

不幸的是,由于派生自CommandPath的所有类都可以直接访问stage,因此编译器现在会抱怨:void changeStage(int&);不再适合,例如,所以你必须改写它...而且它很混乱。

正确的封装要求您不要公开您的属性:它们被定义为private,您永远不会向它们返回句柄。惯用的方法是提供GetSet方法(您不一定要改变它们的类型,或者您可能提供重载等等)。

同样protected是一个相当混蛋的关键字,它不会保护太多,它应该定义的可访问性限制很弱:

class Base { protected: void specialMethod(); };

struct Derived: Base { void specialForward() { specialMethod(); } };

一个简单的派生案例,它现在已公开,这就是为什么它不能用于封装;)