C++: Overriding Public\Private Inheritance

C++: overriding public\private inheritance

If B inherits from A using public, can B override one of the functions and force it to be private?
NO

Eventhough the my_func1() is declared under priavte access specifier it can be still called through a pointer to class A, actually pointing to a object of class B

The call to my_func1() is evaluated at run time depending on the type of objected pointed by the pointer. At compile time the compile sees the my_func1() call as call to A::my_func1() and since A::my_func1() is public the compiler doesn't report only error. It is only at runtime that actual function call B::my_func1() is evaluated.

Ofcourse, You cannot directly call my_func1() through object of class B though because B::my_func1() is declared under Private Access specifier and You cannot access privately declared members from outside the class.

How about the other way around? if the inheritance type is private - can B force a specific function to be public?
NO

If you are calling my_func1() through a pointer of the Base class A, At compile time it is just evaluated as call to A::my_func1() which is Invalid since A::my_func1() is declared private inclass A`

What if A is pure abstract? does it make a difference?
NO
It makes no difference if the base class is Abstract or just polymorphic. Same rules will be applicable.

Would protected make any difference in any combination?
NO
As explained in first 2 Q's if you are calling a virtual function thorough pointer to Base class then at compile time the compiler only checks the access of that member function in Base class because compiler sees it as call to Base class member function. The actual call to the function is evaluated at run time and the feature is called Runtime Polymorphism or Dynamic polymorphism which is independent of the Access specifiers, which as a compile time construct.

So in conclusion,

overriding members of Base Class does not affect access

Why override under private inheritance?

Just one example: A function of Derived::f1() can call a (public or protected) functions of Base::f2(), which in turn can call f(). In this case, dynamic dispatch is needed.

Here is an example code:

#include "iostream"
using namespace std;

class Base {
public:
virtual void f() {
cout << "Base::f() called.\n";
}
void f2() {
f(); // Here, a dynamic dispatch is done!
}
};

class Derived:private Base {
public:
void f() override {
cout << "Derived::f() called.\n";
}
void f1() {
Base::f2();
}
};

int main() {
Derived D;
D.f1();
Base B;
B.f2();
}

Output:

Derived::f() called
Base::f() called

Overriding a publically aliased method via private inheritance

On these two lines within the declaration of Derived, Base is resolved as the the privately-inherited Base type since it is in scope -- even though it is private:

explicit Derived(std::unique_ptr<Base> base) : base_{std::move(base)} {}
// ...
std::unique_ptr<Base> base_;

C++ does not ignore in-scope names that refer to things the current scope doesn't have access to. It seems logical that the compiler would look in an outer scope for a Base that it does have access to, but this is not what happens. The compiler simply stops at the closest Base it sees without regard for any access modifiers.

This can be trivially fixed by referring to the Base type through the top-level namespace prefix :::

explicit Derived(std::unique_ptr<::Base> base) : base_{std::move(base)} {}
// ...
std::unique_ptr<::Base> base_;

Both refer to the same type, but Derived does not have access to the inherited Base name, while it does have access to the global Base name.

You could also fix this issue by redefining what Base means within Derived. At the top of the Derived declaration, you can add:

protected:
using Base = ::Base;

This hides the inherited Base name behind a type alias that Derived does have access to.

C++ override private pure virtual method as public

According to https://en.cppreference.com/w/cpp/language/virtual#In_detail overriding a base's virtual member function only care about the function name, parameters, const/volatile-ness and ref qualifier. It doesn't care about return type, access modifier or other things you might expect it to care about.

The linked reference also specifically notes that :

Base::vf does not need to be visible (can be declared private, or inherited using private inheritance) to be overridden.

Nothing that I can find explicitly gives permission to do this, but the rules of overriding do not prevent it. It's allowed by virtue of virtual functions and function overriding existing and not disallowing this case.

If you are asking why this is how the language is, you may have to ask the standardization committee.

Overriding public virtual functions with private functions in C++

The problem is that the Base class methods are its way of declaring its interface. It is, in essence saying, "These are the things you can do to objects of this class."

When in a Derived class you make something the Base had declared as public private, you are taking something away. Now, even though a Derived object "is-a" Base object, something that you should be able to do to a Base class object you cannot do to a Derived class object, breaking the Liskov Substitution Prinicple

Will this cause a "technical" problem in your program? Maybe not. But it will probably mean object of your classes won't behave in a way your users expect them to behave.

If you find yourself in the situation where this is what you want (except in the case of a deprecated method referred to in another answer), chances are you have an inheritance model where inheritance isn't really modeling "is-a," (e.g. Scott Myers's example Square inheriting from Rectangle, but you can't change a Square's width independent of its height like you can for a rectangle) and you may need to reconsider your class relationships.

Overriding private functions

Why can I override a function that is virtual in a grandparent but not virtual in a parent?

There's no such thing. Once a function is declared virtual, it's implicitly virtual in all derived classes. Only way to come close to "unvirtualize" a member function is to declare it final. That would make it impossible to override it further, but it will still be subject to dynamic dispatch when called via an ancestor reference/pointer. Any access via the child that declared it final or its decedents, could be resolved statically, however.

Why can I override a function that is protected in a grandparent but private in a parent?

Access specifiers don't affect a name's visibility. They only affect where that name can be used. Defining the same function will override the parent's implementation and be called by dynamic dispatch. Again, because this is not something that falls under the realms of "access" to the name.

The child can't refer to the parent's implementation (Parent::foo) if it's private in the parent, and neither can outside code that consumes the interface. It ensure the function is only ever called in a controlled manner. Very useful for testing pre and post conditions.

Accessing a private method in a overridden public method

If you have access to OriginalHandler implementation then make the derived class a nested one:

class A {
private void Foo() { }
protected virtual void Bar() { }

public class B: A {
protected override void Bar() {
Foo(); \\ legal } } }

If you don’t then barring reflection there is no way to access from an external type a private member of another type.

How to prohibit public inheritance but allow private (and protected) inheritance

Interesting question! If you don't mind giving up the destructor's triviality, I think the following does the job:

#include <type_traits>

template <typename T>
class Base {
protected:
~Base() {
static_assert(!std::is_convertible<T*,Base*>::value, "Invalid use of public inheritance.");
}
};

class Derived : public Base<Derived> {
};

int main() {
Derived d;
}

The code above fails to compile: the static_assert fires because Derived* is convertible to Base<Derived>*. However if you change the inheritance to either protected or private then the code compiles.

Unfortunately users can still shoot themselves in the foot:

class Bad : public Base<Derived> {
};

private inheritance

From a common understanding of inheritance, C++’ “private inheritance” is a horrible misnomer: it is not inheritance (as far as everything outside of the class is concerned) but a complete implementation detail of the class.

Seen from the outside, private inheritance is actually pretty much the same as composition. Only on the inside of the class do you get special syntax that is more reminiscent of inheritance than composition.

There’s a caveat though: C++ syntactically treats this as inheritance, with all the benefits and problems that this entails, such as scope visibility and accessibility. Furthermore, C-style casts (but no C++ cast!) actually ignores visibility and thus succeeds in casting your Derived pointer to Base:

Base* bPtr = (Base*) new Derived();

Needless to say, this is evil.



Related Topics



Leave a reply



Submit