简体   繁体   English

抽象类C ++中的变量

[英]variables in abstract classes C++

I have an abstract class CommandPath, and a number of derived classes as below: 我有一个抽象类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();
};

All of the derived classes have the member variable 'stage'. 所有派生类都有成员变量'stage'。 I want to build a function into all of them which manipulates 'stage' in the same way, so rather than defining it many times I thought I'd build it into the parent class. 我想在所有这些中构建一个函数,它以相同的方式操纵'stage',所以我没有多次定义它,而是认为我将它构建到父类中。 I moved 'stage' from the private sections of all of the derived classes into the protected section of CommandPath, and added the function as follows: 我将'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();
};

Now my compiler tells me for the constructor lines that none of the derived classes have a member 'stage'. 现在我的编译器告诉我构造函数行,没有派生类有成员'stage'。 I was under the impression that protected members are visible to derived classes? 我的印象是受保护的成员对派生类是可见的?

The constructor is the same in all classes, so I suppose I could move it to the parent class, but I'm more concerned about finding out why the derived classes aren't able to access the variable. 所有类中的构造函数都是相同的,所以我想我可以将它移动到父类,但我更关心的是找出派生类无法访问变量的原因。

Also, since previously I've only used the parent class for pure virtual functions, I wanted to confirm that this is the way to go about adding a function to be inherited by all derived classes. 此外,由于以前我只使用父类用于纯虚函数,我想确认这是添加要由所有派生类继承的函数的方法。

Try this: 尝试这个:

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

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

(Omitted extra code for brevity). (为简洁起见,省略了额外的代码)。

You can't use the initializer list on a parent class' members, only the current one's. 您不能在父类的成员上使用初始化列表,只能使用当前的成员。 If that makes sense. 如果这是有道理的。

First of all: don't use protected for attributes. 首先:不要使用protected属性。

It may seem arbitrary, but the point is that it breaks encapsulation. 它似乎是随意的,但重点是它打破了封装。 Imagine that suddenly you realize what of space it is to use an int when an unsigned short would have done, so you go ahead and change CommandPath . 想象一下,突然你意识到当一个unsigned short已经完成时使用int的空间是什么,所以你继续改变CommandPath

Unfortunately, since all the classes deriving from CommandPath could access stage directly, there is a strong change the compiler will complain now: void changeStage(int&); 不幸的是,因为从CommandPath派生的所有类都可以直接访问stage ,所以编译器现在会抱怨: void changeStage(int&); is no longer suitable for example, so you have to reword it... and it's messy. 不再适用于例如,所以你必须改写它......而且它很混乱。

Proper encapsulation requires that you don't expose your attributes: they are defined as private and you never return handles to them. 正确的封装要求您不要公开您的属性:它们被定义为private ,您永远不会向它们返回句柄。 The idiomatic way is to provide Get and Set methods (you don't necessarily have to change their type, or you may provide overloads, etc...) 惯用的方法是提供GetSet方法(你不一定要改变它们的类型,或者你可能提供重载等等)

Also protected is quite a bastard keyword, it does not protect much and the accessibility restriction it is supposed to define is weak: protected是一个相当混蛋的关键字,它不会保护太多,它应该定义的可访问性限制很弱:

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

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

A simple case of deriving and it's now public, that's why it can't be used for encapsulation ;) 一个简单的派生案例,它现在是公开的,这就是为什么它不能用于封装;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM