I am currently working with Big C++ 2nd Edition, using Code::Blocks 17.12, on the chapter for inheritance
The book introduces the protected variable type for cases in which you want to allow a derived class to access said variable.
The book also forewarns that protected elements suffer from some of the pitfalls of a public variable: in the worst cases derived class members can corrupt the base class data
The book demos the use of a protected member in a clock program in a dedicated section in which they introduce this, but in the final code they ultimately went with setting the variable to private and then using some get_ helper functions to access this private data. This combo of private and using helper functions always returned errors in my IDE and I wasn't able to pull that off
Take this simple example I created for P8.1, a employee record for a programmer, with an employee base class and programmer derived class. I created the following ctor, with the variables name and sal set to protected status in the base class
Programmer::Programmer(string p_name, double p_sal)
:Employee(get_name(), get_sal())
{
name=p_name;
sal=p_sal;
}
With this code, the program works perfectly.
Based on the textbook, if the variables name and sal were set to private status in the base, then I should be able to execute the code also, granted that I am using a get_ helper function I created to accessed the data.
Can anyone explain what the issue is here? Should I be ok with using protected or is there truly a way to keep all of my variables private for classes?
I also found this on https://learn.microsoft.com/en-us/cpp/cpp/protected-cpp?view=vs-2019
Protected members that are also declared as static are accessible to any friend or member function of a derived class. Protected members that are not declared as static are accessible to friends and member functions in a derived class only through a pointer to, reference to, or object of the derived class.
I have not covered static so far, So I ultimately tried a bunch of different combinations with pointers and references, none of which worked either.
I am trying to understand when to use protected vs when to use private basically and the book isn't being clear on that. Any ideas?
For some reason I thought when calling the base class constructor you needed to provide helper functions to access the private data.
Since the base ctor is already public, and by feeding it the parameters for the derived class ctor it will construct the derived class obj properly, allowing get_ func's to read its private variables
Programmer::Programmer(string p_name, double p_sal)
:Employee(p_name, p_sal)
{}
I wasn't understanding this in the book, thank you all for helping clarify
Related
When should I mark the static method of a specific class as private other than public?
What aspects should I consider when making such considerations.
What are the advantages for mark the static method as private?
Any simple example would be appreciated, which could help me fully understand this matter.
UPDATE:
As per this answer, which says that[emphasise mine]:
This function could easily have been made freestanding, since it doesn't require an object of the class to operate within. Making a function a static member of a class rather than a free function gives two advantages:
It gives the function access to private and protected members of any object of the class, if the object is static or is passed to the function;
It associates the function with the class in a similar way to a namespace.
How to fully understand the statements above?
The general rule for methods (static or otherwise) is to make them private if possible — i.e. unless you absolutely need them to be callable from other classes (which is to say, you need them to be part of your class’s public API)
The reason for making as much as possible private is simple: in the future, you’ll be able to change anything that is private, without breaking a bunch of other classes that were written to call the old version of the method. Changing a public method is more problematic, because other classes might be depending on it.
I currently have a class that processes files on a local file system.
Class FileProcessor
{
public:
UpdateFiles();
private:
processFiles();
checkFileIsCorrupted();
}
Now, I want to add a new functionality, where the same file processing is done on files that first needed to be downloaded, but then it would call processFiles() and checkFileIsCorrupted() as before and do the same processing.
I'm wondering what's the best way to do this is.
I could change the interface for UpdateFiles() and add a parameter do determine whether I need to download the files, but modifying the public interface is clearly not ideal.
I could add a new public interface function UpdateFilesFromRemote() and thus share the private members, though this would seem to violate the single responsibility principle, which would call for the "new" functionality to be its own class.
Make a new class. This would either duplicate all the code in processFiles() and processData(), or require a new base class where processFiles() and checkFileIsCorrupted() are protected members,and all the private member they call on would also need to be moved to protected in this base class as well. However, from what I've read so far, most people seem to consider using protected to be something to avoid.
Make a new class and make processFiles() and checkFileIsCorrupted() friends of both classes. I'm assuming this would require both functions to take FileProcessor and the new class as objects (or a base class interface), so that the private members can be accessed. Although both FileProcessor and the new class would share many private members, and so that would still require them to be protected in the base class interface. Also, having a design where checkFileIsCorrupted() needs to take a FileProcessor object as input just... doesn't feel right. After all, its not actually modifying the FileProcessor object, its just a helper function to check if a file is corrupted.
Make a new class and make processFiles() and checkFileIsCorrupted() non member, non friend functions. This would mean that internal file information that is private to both classes would need to be passed as function parameters to these non-member, non friend functions, breaking encapsulation.
Either way, no solutions seems to be "good". Is there any better way to design this?
Thanks.
Invoking a protected constructor in a derived class is not allowed, as explained here.
The accepted answer explains that protected grants access to members of an object of base class A only when that object of class A is a subobject of class B. So far, so good.
But then, why is it allowed (at least in GCC 4.6.3) to call static protected methods? Specifically, it doesn't make any sense to me that the following compiles, while the commented line does not:
class A
{
protected:
A() {}
static A makeA() { return A(); }
};
class B: public A
{
public:
static A makeAFromB()
{
return makeA(); // compiles
// return A(); // does not compile
}
};
Philosophically, a constructor is pretty much like a static method returning an object of class A, reason why I don't get the difference in behaviour here.
But then, why is it allowed (at least in GCC 4.6.3) to call static protected methods?
Because that's what the Standard says. The constraints that apply to the accessibility of protected members (and that the answer you linked explains very well) are defined in paragraph 11.4/1 of the C++11 Standard, whose first sentence specifies:
An additional access check beyond those described earlier in Clause 11 is applied when a non-static data
member or non-static member function is a protected member of its naming class (11.2). [...]
The additional access check does not apply to static members or static member functions.
You're right that the way protected only grants access to the embedded base object can be surprising... but there's a good reason for it. Say you have a couple classes derived from Base, and a method in one of those classes wanted to do things to an arbitrary Base object via some reference or pointer... it might be that the Base it's fiddling with is part of the other derivation chain, which has other behavioural expectations of the Base object given the usage it makes of the protected member functions. You're effectively removing the encapsulation that the other derived class intended, preventing it enforcing intended invariants, stepping outside the world of good OO behaviours.... Applying this insight to your specific scenario, the C++ rules are preventing you using that protected constructor to make a subobject that was expected to have invariants policed by some derived class, when there is actually no derived object into which that Base object will be embedded.
Separately, the way protected works for constructors has clear utility - it prevents construction of the class (using that constructor) except as a subobject of the derived class, or from member functions of the base class (such as makeA in your example) - whether they're static or non-static member functions is irrelevant... all member functions always have full to the class.
What would be the utility in ignoring the intuitive meanings of private/protected/public for static member functions? You're saying you expect them to be effectively private, if that's behaviour you want then just make them private / if you need them accessible leave them protected. Clearly the protected access is limited as per the justification in my first paragraph.
Static methods are inherited in the sense that they're available amongst the child class's methods. We can call a static method using the child class's name, or using an instance of the child class, or without qualification in the body of a child class.
Bjarne Stroustrup once said that he can address most of the tasks with ONLY private or public member variables and he seldom uses protected member variables in his design. I have heard similar arguments in other places. Here is an example,
class BaseClass
{
...
private:
int m_iAge;
double m_dSalary;
string m_strName;
bool m_bGender;
}
class SubClass : public BaseClass
{
...
}
Given the above class design, how the subclass SubClass can use the variables defined in BaseClass?
Question1> Why we should prefer to having private rather than protected variables? Is it the reason that the BaseClass can hide the implementation detail and make it easy for further improvement?
Question2> In order to let the SubClass access the variable defined in BaseClass, it seems to me that we have to define public access(get/set). However, getter/setter are evil! So the second choice is to define protected access(get/set). Any better idea?
Thank you
Bjarne's point is that generally the derived class shouldn't access the variables of the base class -- doing so frequently leads to maintenance problems. And no, changing it to use get/set (accessor/mutator) functions isn't an improvement.
Ask yourself - why would the derived class ever change the value of m_bGender? Or m_iAge? Doesn't the base class already handle these values correctly?
See, there is generally no need to have direct access to the internals of the base class. So we make them private, and use the class' public interface.
In some very rare cases, there might also be one or two protected functions, if derived classes need some special interface. But that is unusual. If derived classes have different behaviour, we more often use virtual functions for that.
I think the rationale for this claim is that in many situations, subclassing doesn't often change the behavior of the existing (inherited fields), but rather one adds fields and adds new methods that manipulate the new fields.
If you are looking for a way to manipulate inherited members w/o protected, you can, in the base class, make the derived class a friend. You would have to know it ahead of time, though.
The only main reason to use private over protected members is if they indeed are not required in child implementations. That's why we have protected members, because there are cases where the child class does need direct access to members of a parent class. I think Stroustrup is referring to a design whereby there is little need to access parent members in the first place, and child classes simply build upon the functionality of their parent rather than modify the functionality of their parent.
However, getter/setter are evil!
Why so? Getters and setters are an important part of OOP from my experience. There are good reasons to make an interface with a class, rather than access its variables directly.
I just want to make sure I got the idea of public and private right.
Regarding the private access specifier, does it mean:
Only accessed inside the class
Cannot be accessed from the object of the class unless there are public class methods that can be used to access them (Can other objects use those public functions?)
No other object can access them
And for public:
Accessed from the object of the class
Accessed from any other object
Is that right?
private : Only member functions and friends of class can access it.
public : Can be accessed anywhere where the object has scope.
Answering the questions -
private:
Yes
Yes. (Can other objects use those public functions? With out having class relations, one object of class cannot communicate to the other's members. )
Friends has access to private members of a class. So, answer depends upon your class has friends or not.
public:
Yes
Depends whether the object has hierarchical relations to the member's class you are trying to access.
I think there is an issue of vocabulary to begin with.
In C++ (and most languages) a class is a type. You can think about it as a blueprint to actually build something.
it describes the attributes that are held
it describes the methods to operate on those attributes
it describes the restrictions that apply: this is the "accessibility"
An object is produced by actually instantiating a class, that is, building what the blueprint described. It is more or a less a bundle of attributes. You can have several objects of the same class as you can have several houses from the same blueprint: note that their physical location is different for obvious reasons :)
Now, on to the accessibility. There are 3 typical levels of accessibility: public, protected and private.
public, as expected, means that everyone is given access to either attributes or methods
protected is somewhat less trivial. It means that only the object, or its children, may access the attributes (bad idea*) or methods. (Plus, in C++, friends)
private means that only the objects of that class (and not their children) may access the attributes or methods (Plus, in C++, friends)
Note: whatever the level of accessibility, an object has unrestricted access to all the attributes and methods of any object of the same class.
(*) Even though it pops up now and there, it is generally a bad idea to use protected attributes. The point of encapsulation is to hide the details, not only for the sake of it, but because by precisely controlling who can access the data, we can ensure that the class maintains its invariants (simple example, an array where you would store the size separately, you need to ensure that the "size" really represents the number of items in the array, at all times). Note: this restriction does not apply when you can seal a hierarchy, like in C# for example.
Private members can only be accessed by member functions and static functions of the same class and by friends of the class. It does not matter on which object that function is called. So the case
class Foo
{
private:
void bar() {}
public:
void baz(Foo& var)
{
var.bar();
}
}
is perfectly legal.
That seems correct. Data members and functions marked public can be accessed from anywhere by anyone. Data members and functions marked private can only be accessed by the class and its friends. However, a member function of a class can access data with any access specifier, so a public function can read and write private data members (this is used universally in OOP).
In c++ data and fn are encapsulated as 1 unit.
We begin a program by writing
preprocessor directives
Then, class declaration
Followed by function(fn) declaration where we also specify the access modifier ( public, private or protected)
& finally the main () program.
If we declare a fn
Private:the data within an object of a class is only accessed by fn defined within it- (the object which has the data and the private fn)
Public:the data can be accessed by any fn
Protected:similar to private however data can also be accessed by sub-classes that inherit the properties of another class.
Example if class A inherits from class B, thenA is a subclass of B.