抽象类 C++ 中的变量

发布于 2024-09-01 12:51:33 字数 1286 浏览 5 评论 0原文

我有一个抽象类 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”从所有派生类的私有部分移至 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” 。我的印象是受保护的成员对派生类可见?

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

另外,由于以前我只将父类用于纯虚函数,所以我想确认这是添加由所有派生类继承的函数的方法。

I have an abstract class CommandPath, and a number of derived classes as below:

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'. 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. 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:

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'. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

别挽留 2024-09-08 12:51:33

试试这个:(

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

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

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

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

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.

暮年慕年 2024-09-08 12:51:33

首先:不要对属性使用protected

这看起来可能是任意的,但关键是它破坏了封装。想象一下,您突然意识到,当使用 unsigned Short 就可以完成时,使用 int 需要多大的空间,因此您继续更改 CommandPath

不幸的是,由于从 CommandPath 派生的所有类都可以直接访问 stage,因此编译器现在会抱怨一个强烈的变化: void changeStage(int&);<例如, /code> 不再适合,所以你必须重新措辞......而且它很混乱。

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

另外 protected 是个混蛋关键字,它没有提供太多保护,而且它应该定义的可访问性限制很弱:

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

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

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

First of all: don't use protected for attributes.

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.

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&); 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. 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...)

Also protected is quite a bastard keyword, it does not protect much and the accessibility restriction it is supposed to define is weak:

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 ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文