28

i have an inheritance struct A : public B, i want to hide individual functions from B, is this possible?

i know the opposite is possible using using BMethod in the A declaration.

cheers

lurscher
  • 25,930
  • 29
  • 122
  • 185

10 Answers10

58

If you want to selectively hide functions from B it does not make much sense to use public inheritance in the first place.
Use private inheritance & selectively bring methods from B into the scope of A:

struct B{
   void method1(){};
   void method2(){};
};
struct A : private B{
   using B::method1;
};

A a;
a.method1();
a.method2(); //error method2 is not accesible
Eugen Constantin Dinca
  • 8,994
  • 2
  • 34
  • 51
30

There is an issue here: this would be a direct violation of the Liskov Substitution Principle, namely A would not act as a B any longer.

If you wish to reuse B implementation, the solution is simply to do so:

class A
{
public:
  void foo() { return b.foo(); }
  void bar() { return b.bar(); }
  // ...

private:
  B b;
};

Don't abuse inheritance, use composition instead

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • 10
    Just happen to have to write a class that was 99% of another class, but handle things differently and had 1 function, just one function that could not exist in B. – rxantos Mar 10 '16 at 07:34
  • 2
    It is not necessarily inheritance abuse, it just means that B is not a subtype of A (as in public inheritance), but B is implemented in terms of A, so LSP is not affected. I believe the "use composition instead" is generally a good advice, but non-public inheritance can be a useful tool implementing Facade pattern, i.e. look how bloated javax.swing.JButton is. – Jan Turoň Mar 25 '18 at 10:05
  • 1
    @JanTuroň: Note that private inheritance means that LSP applies to all who access to the innards of the class: the class itself, its children classes and its friends. And those may accidentally call a method on the base, or pass a reference/pointer to base to an unrelated function. By being more deliberate, composition helps protecting better against Murphy. – Matthieu M. Mar 25 '18 at 10:43
  • That is, of course, matter of design. I think compilers should at least issue warning if one tries to cast down from B to A if the inheritance is non-public. See *Should I pointer-cast from a private derived class to its base class?* [here](https://isocpp.org/wiki/faq/private-inheritance). – Jan Turoň Mar 25 '18 at 12:33
  • *hide* base class methods doesn't necessary mean they would not work, rather they can clutter the interface with no benefit. – apple apple Jan 12 '23 at 19:37
  • I feel this is a somewhat fastidious adherence to rather academic rules, if you have to wrap 20 methods I'd question why you didn't just just inherit. – c z Feb 02 '23 at 11:57
  • @cz: I do agree it's fastidious, due to a lack of delegation syntax. The reason NOT to inherit, of course, is to avoid exposing any _other_ method -- now or in the future. – Matthieu M. Feb 02 '23 at 12:29
30

The using keyword can be used to change visibility

struct A
{
    void method1();
};

struct B: public A
{
    void method2();

    private:
    using A::method1;
};
xaviersjs
  • 1,579
  • 1
  • 15
  • 25
  • Thank you! This is the actual answer to the OP question, as posed. The other posts are just different permutations of wrong answers. – Dess Dec 27 '22 at 08:20
  • It is still possible to call `method1`: `B b; b.A::method1()`. – anton_rh Feb 15 '23 at 17:15
17

Aside from the ways described in the previous answers—composition, private inheritance, and non-private inheritance but with the inherited method declared private—another way is to explicitly delete the inherited method:

#include <iostream>

struct A {
    void foo() { std::cout << "foo\n"; }
};

struct B : A {
    void foo() = delete;
};

int main() {
    B b;
    b.foo(); // COMPILER ERROR
}

Although the b.foo() call produces a compiler error, client code can still call the base class’s version by qualifying with the base class identifier A:

b.A::foo(); // compiles, outputs 'foo' to console

This explicit deletion way works when foo is not a virtual non-deleted method in A. By C++11 Standard §10.3/16, this explicit deletion is ill-formed when the deleted method in the derived class overrides a virtual non-deleted method of the base class. For more info on this restriction, see the answers to the SO question C++11 Delete Overriden Method.

Community
  • 1
  • 1
CodeBricks
  • 1,771
  • 3
  • 17
  • 37
9

You can't "hide it" per se, but you can make it a compile time error to call it. Example:

struct A
{
    void AMethod() {}
};

class B : public A
{
    void AMethod() {} //Hides A::AMethod
};

int main()
{
    B myB;
    myB.AMethod(); //Error: AMethod is private
    static_cast<A*>(&myB)->AMethod(); //Ok
    return 0;
}

Examples on codepad with the error, and without.

That all said, despite this being possible, you really shouldn't do it. You'll confuse the hell out of clients.

EDIT: Note that you can also do this with virtual functions (And with the error).

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • I don't think there's any need to define the (private) AMethod in inheriting class B. Declaration will, I think, suffice. I'd say the original method is "hidden", if it's a compile-time error trying to use it (even if the error message differs from the case where the method doesn't exist at all). – eq- Feb 05 '11 at 18:18
  • @eq: That is correct, there's no need to define it unless the method in the parent class is `virtual` . (I just got lazy and used copy/paste to make `B`) – Billy ONeal Feb 05 '11 at 18:59
4

To those that are suggesting composition... this might not be the best possible way of going about things. My understanding is that the Liskov Substitution Principle only states that there's the possibility of the functions from the base class being used on the child, not that they necessarily should be. For example, for a particular base class you may have multiple functions that essentially perform the same operation, but for different specific cases. In the derived class you may want to abstract these public functions away in favor of simplifying the user's interface. This is where private inheritance can be used. Private inheritance might also be a necessity, if we have protected functions in the base class that we don't want the user of the base class to call, yet would be invaluable to the derived class.

In short, if you HAVE to, use private inheritance, but composition is preferred in most cases.

It'sPete
  • 5,083
  • 8
  • 39
  • 72
4

There is yet another approach.

class A{
    void f1();
    void f2();
    void f3();
}

class BInterface{
    void f2();
    void f3();
}

class B : public A, BInterface
{
}

BInterface b = new B();
b->f1(); //doesn't work since f1 is not declared in BInterface
b->f2(); //should work
b->f3(); //should work
delete(b);

Use BInterface as a filter for inherited classes to exclude undesirable methods. Liskov Substitution principle isn't violated in this case since an object of BInterface class is not an object of A class even though that an object of B class is an object of BInterface class.

2

If the methods are private in B, then they will remain hidden to a even if you use public inheritance.

DPD
  • 1,734
  • 2
  • 19
  • 26
0

Can't alter the visibility of the original method.

You could create a method in struct A with the same name and have that method be private, but that doesn't prevent the method from being called when an instance of struct A is being referenced by a variable of type B.

ClosureCowboy
  • 20,825
  • 13
  • 57
  • 71
0

Why don't you make it Virtual in the base class and override it in its Children? (more help)