Variables in C ++ Abstract Classes

I have an abstract CommandPath class and a series of derived classes, as shown 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 derived classes have a member variable called 'stage'. I want to create a function in all of them that manipulates the β€œscene” in the same way, so instead of defining it many times, I thought I would create it in the parent class. I moved the β€œstage” from the private partitions of all derived classes to the protected CommandPath section 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 about the constructor lines that none of the derived classes have a "stage" member. Do I have the impression that protected members are visible to derived classes?

The constructor is the same in all classes, so I can move it to the parent class, but I'm more worried about why the derived classes cannot access the variable.

Also, since I previously used only the parent class for pure virtual functions, I wanted to confirm that this is a way to add a function that will be inherited by all derived classes.

+4
source share
2 answers

Try the following:

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

(additional code added for brevity).

You cannot use the initialization list for members of the parent class, only for the current one. If that makes sense.

+13
source

First of all: do not use protected for attributes.

It may seem arbitrary, but the fact is that it destroys encapsulation. Imagine that suddenly you realize that you should use int from outer space if you would have unsigned short , so you go CommandPath and change CommandPath .

Unfortunately, since all classes originating from CommandPath can directly access stage , there is a strong change that the compiler will now complain about: void changeStage(int&); no longer suitable, for example, you need to rewrite it. and it's messy.

Proper encapsulation requires that you not expose your attributes: they are defined as private , and you never return descriptors to them. The idiomatic way is to provide Get and Set methods (you don't have to change their type, or you can provide overloads, etc.)

Also protected is a pretty bastard keyword, it does not protect much, and the accessibility restriction that is supposed to be determined is weak:

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

A simple case of inference and now it is publicly available, so it cannot be used for encapsulation;)

+4
source

Source: https://habr.com/ru/post/1309910/


All Articles