抽象类 C++ 中的变量
我有一个抽象类 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
试试这个:(
为了简洁省略了额外的代码)。
您不能在父类的成员上使用初始化列表,只能在当前的成员上使用。如果这是有道理的话。
Try this:
(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.
首先:不要对属性使用
protected
。这看起来可能是任意的,但关键是它破坏了封装。想象一下,您突然意识到,当使用
unsigned Short
就可以完成时,使用int
需要多大的空间,因此您继续更改CommandPath
。不幸的是,由于从
CommandPath
派生的所有类都可以直接访问stage
,因此编译器现在会抱怨一个强烈的变化:void changeStage(int&);<例如, /code> 不再适合,所以你必须重新措辞......而且它很混乱。
正确的封装要求您不要公开属性:它们被定义为
private
并且您永远不会返回它们的句柄。惯用的方法是提供Get
和Set
方法(您不一定必须更改它们的类型,或者您可以提供重载等...)另外
protected
是个混蛋关键字,它没有提供太多保护,而且它应该定义的可访问性限制很弱:一个简单的派生案例,现在是公共的,这就是为什么它不能用于封装; )
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 anunsigned short
would have done, so you go ahead and changeCommandPath
.Unfortunately, since all the classes deriving from
CommandPath
could accessstage
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 provideGet
andSet
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:A simple case of deriving and it's now public, that's why it can't be used for encapsulation ;)