While finding answer for this query with writing test code, I got to know that private/protected inheritance changes the way exceptions are received from various classes, which was very surprising. To find the answer I referred earlier forum questions and I came across this similar question.
For me it's quite obvious to use protected inheritance for a base class with virtual methods. Keeping the standard aside, I wanted to know why in C++ exception handling is restricted by inheritance when virtual method calls are Not ?
Following snippet explains it:
struct Base { virtual void printError () = 0; };
class Derived : protected Base { void printError () { } };
int main ()
{
try {
throw new Derived;
}
catch(Base *p) { p->printError(); } // Ideal; but not invoked
catch(void *p) { ((Base*)p)->printError(); } // Ugly; but only way to invoke
}
Edit:
If we consider the privacy regard as an answer; accepted. But then why it's applicable only for catch() receiving base pointers, while it's not applicable for functions receiving base pointers ?
The meaning of private and protected inheritance is that no one outside of the class or class hierarchy can know about the inheritance. This is the same way as no one outside the class can know about a private member.
Catching a derived class by its base class revealed to the catcher that the derived class is infact derived from the base class and is a breach of the privacy of the inheritance.
protected inheritance means only Derived and its subclasses "knows" it also is-a Base. main, and the catch statement, doesn't "know" this. This is the point of inheriting with a specific access.
Virtual dispatch doesn't care about this - if you have access to call a virtual function, then virtual dispatch is used.
In your sample, you cannot use a Derived as if it was a Base anywhere else in the scope of main - so it makes sense that you can't do it in the catch either
Related
I am learning the concepts of OOPS, and came across private inheritance. From what I've learnt - When a class derives from a base class and letter when the derived class is instantiated, the constructor of the Base class is called first, followed by the constructor of the derived class. So, in the code "A created" would be printed first.
The problem is since the inheritance is private, all the members of A would be private inside B, so how can the constructor of A be called when B is instantiated. Going by this logic, the following code should generate errors, but when I run it, it compiles fine, and gives the output "A created" followed by "B created".
How is this happening? Or am I making some mistake in understanding the concept?
#include <iostream>
using namespace std;
class A{
public:
A(void)
{
cout<<"A created"<<endl;
}
~A()
{
//do nothing
}
void doSomething(void)
{
cout<<"hi";
}
};
class B:private A
{
public:
B(void)
{
cout<<"B created"<<endl;
}
~B()
{
//do nothing
}
};
int main() {
B* myptr = new B();
//myptr->doSomething();
delete myptr;
return 0;
}
B can call public (and protected) methods of A, since A constructor is public B can call it.
Please see following link to better understand c++ private inheritance:
Difference between private, public, and protected inheritance
The access specifier for inheritance limits access to code outside the derived class; think to the base class A as if it were a normal private field:" the outside" can't see it, but B can use it freely from "the inside".
As for the constructor, it's implicitly called by B's constructor, so there's no problem (and, besides, otherwise private inheritance would be unusable).
Still, don't worry too much about private inheritance, it's useful in extremely rare cases (I've never seem it actually used in real life, and for this reason many languages don't even support it), normally composition (using a normal private field) is a better and simpler way.
Here is good short article about private inheritance which illustrates in details what is private inheritance, when it is useful and when it should be avoided in favour of inclusion.
In short:
Inheritance access modifier limits access to basic class properties and methods not for derived class but for code which uses derived class.
This is useful to 'replace' (not 'extend') basic class interface for users of inherited class.
In general it's considered better to include basic class member rather than use private inheritance.
If you need to reuse some methods of basic class which rely on virtual functions and you need to override virtual functions (but you still want to hide part of basic class interface from external code), this is more appropriate case for private inheritance.
Hope this will help.
I have a base class that clients can "shut down":
struct base {
void shutdown() {
//code
}
};
But clients can (if they want) create a subclass to suit their own needs:
struct der : public base {
void shutdown(double some, int other, bool parameters) {
//custom shutdown stuff
base::shutdown(); //<- thus MUST be called
}
};
The problem is that the client must remember to call base::shutdown() (the superclass creator will document this to subclass developers). This seems error-prone, as nothing is enforced at compile-time.
Are there alternative design patterns to solve this in some way?
Unfortunately, this is one of those cases where you "have to do the right thing" when writing the code. This applies to many things in programming. If you don't do the right calculations when calculating something, that's also wrong. Or if you call a function twice that should only be called once. Or not calling it at all when it has to be called. All of these things are "doing it wrong". You can't prevent programmers from making mistakes...
Of course, if you hadn't added a bunch of extra parameters, you could do it "in reverse" by having a non-virtual function in the base-class that doesn't get overridden, and then let the base-class call a virtual function in the derived class. As I said, it doesn't work if you have parameters that aren't present in the base class that needs to go into the derived class.
An example of what I mean:
struct base {
void shutdown() final { // final: it can't be overridden in derived class
do_shutdown(); // Calls derived function's
// ... more code here ...
}
virtual void do_shutdown() { } // default is "do nothing".
};
struct der: public base
{
// not overriding `shutdown`, but overriding `do_shutdown`
void do_shutdown()
{
.. some code goes here ..
}
}
Now the call to der->shutdown() will call the base-class's implementation, which calls do_shutdown in the derived class before completing the in the base-class's shutdown.
However, like I said, you can't add extra parameters when you do this - in fact, deriving a class and changing the parameters is "wrong" - not so wrong you can't possibly ever do it, but it tends to be a bad thing when using inheritance polymorphism, because the whole purpose of polymorphism is that there is some common code that "doesn't know if it's a base class object, a derived1 object or a derived2 object" - so if it needs to know which kind of object to pass the correct number of arguments, it gets a bit meaningless.
I wouldn't worry about it. It's similar to the assignment operator of derived classes. It's not your fault if the subclass developer forgets to call it, but it's not an error if it isn't either.
C++ FAQ entry on the subject
Consider the following code:
class Base
{
public:
virtual void Foo() {}
};
class Derived : public Base
{
private:
void Foo() {}
};
void func()
{
Base* a = new Derived;
a->Foo(); //fine, calls Derived::Foo()
Derived* b = new Derived;
// b->Foo(); //error
static_cast<Base*>(b)->Foo(); //fine, calls Derived::Foo()
}
I've heard two different schools of thought on the matter:
Leave accessibility the same as the base class, since users could use static_cast<Derived*> to gain access anyway.
Make functions as private as possible. If users require a->Foo() but not b->Foo(), then Derived::Foo should be private. It can always be made public if and when that's required.
Is there a reason to prefer one or the other?
Restricting access to a member in a subtype breaks the Liskov substitution principle (the L in SOLID). I would advice against it in general.
Update: It may "work," as in the code compiles and runs and produces the expected output, but if you are hiding a member your intention is probably making the subtype less general than the original. This is what breaks the principle. If instead your intention is to clean up the subtype interface by leaving only what's interesting to the user of the API, go ahead and do it.
Not an answer to your original question, but if we are talking about classes design...
As Alexandrescu and Sutter recommend in their 39th rule, you should prefer using public non-virtual functions and private/protected virtual:
class Base {
public:
void Foo(); // fixed API function
private:
virtual void FooImpl(); // implementation details
};
class Derived {
private:
virtual void FooImpl(); // special implementation
};
This depends on your design, whether you want to access the virtual function with a derived class object or not.
If not then yes, it's always better to make them private or protected.
There is no code execution difference based on access specifier, but the code becomes cleaner.
Once you have restricted the access of the class's virtual function; the reader of that class can be sure that this is not going to be called with any object or pointer of derived class.
Say I have an abstract class
class NecessaryDanger
{
public:
virtual void doSomethingDangerous() =0;
}
and a class that is derived from this class:
class DoesOtherStuff : public NecessaryDanger
{
//stuff
void otherMethod();
void doSomethingDangerous();
}
is there a way I can only allow access of doSomethingDangerous() like
DoesOtherStuff d;
d = DoesOtherStuff();
d.otherMethod(); //OK
d.doSomethingDangerous(); //error
NecessaryDanger* n = &d;
n->doSomethingDangerous(); //OK
I am not very good at C++ yet, so the code above may not be quite right, but you maybe get the idea. I have a set of classes that need to have the ability to do "something dangerous" (in their own special way) that could cause problems if more than one object of these classes does this dangerous thing. I would like to have a manager class that has a NecessaryDanger pointer to only one object. If the method doSomethingDangerous could only be called by a NecessaryDanger object, then it would be more difficult for an accidental call to doSomethingDangerous to happen and cause me headaches down the road.
Thanks in advance for the help. Sorry in advance if this is a dumb question!
Sure. Just make it private in the derived class and public in the base.
Of course, if NecessaryDanger is a public base, then anyone can cast and call. You might want to make it a private base and use friend.
class DoesOtherStuff : private NecessaryDanger
{
//stuff
void otherMethod();
private:
void doSomethingDangerous();
friend class DangerManager;
}
Remove the virtual classifier in the superclass so that the compiler does compile-time binding based on the variable type instead of run-time binding based on the object type.
Building on Potatswatter's response :)
Here is Herb's advice: (especially 1 and 2) applicable in this context.
Guideline #1: Prefer to make
interfaces nonvirtual, using Template
Method.
Guideline #2: Prefer to make
virtual functions private.
Guideline #3: Only if derived classes need to invoke the base implementation of a
virtual function, make the virtual
function protected.
For the special case of the destructor
only:
Guideline #4: A base class destructor
should be either public and virtual,
or protected and nonvirtual.
While I've seen rare cases where private inheritance was needed, I've never encountered a case where protected inheritance is needed. Does someone have an example?
People here seem to mistake Protected class inheritance and Protected methods.
FWIW, I've never seen anyone use protected class inheritance, and if I remember correctly I think Stroustrup even considered the "protected" level to be a mistake in c++. There's precious little you cannot do if you remove that protection level and only rely on public and private.
There is a very rare use case of protected inheritance. It is where you want to make use of covariance:
struct base {
virtual ~base() {}
virtual base & getBase() = 0;
};
struct d1 : private /* protected */ base {
virtual base & getBase() {
return this;
}
};
struct d2 : private /* protected */ d1 {
virtual d1 & getBase () {
return this;
}
};
The previous snippet tried to hide it's base class, and provide controlled visibility of bases and their functions, for whatever reason, by providing a "getBase" function.
However, it will fail in struct d2, since d2 does not know that d1 is derived from base. Thus, covariance will not work. A way out of this is deriving them protected, so that the inheritance is visible in d2.
A similar example of using this is when you derive from std::ostream, but don't want random people to write into your stream. You can provide a virtual getStream function that returns std::ostream&. That function could do some preparing of the stream for the next operation. For example putting certain manipulators in.
std::ostream& d2::getStream() {
this->width(10);
return *this;
}
logger.getStream() << "we are padded";
C++ FAQ Lite mentions of a case where using private inheritance is a legitimate solution (See [24.3.] Which should I prefer: composition or private inheritance?). It's when you want to call the derived class from within a private base class through a virtual function (in this case derivedFunction()):
class SomeImplementationClass
{
protected:
void service() {
derivedFunction();
}
virtual void derivedFunction() = 0;
// virtual destructor etc
};
class Derived : private SomeImplementationClass
{
void someFunction() {
service();
}
virtual void derivedFunction() {
// ...
}
// ...
};
Now if you want to derive from the class Derived, and you want to use Base::service() from within the derived class (say you want to move Derived::someFunction() to the derived class), the easiest way to accomplish this is to change the private inheritance of Base to protected inheritance.
Sorry, can't think of a more concrete example. Personally I like to make all inheritance public so as to avoid wasting time with "should I make inheritance relation protected or private" discussions.