a way in c++ to hide a specific function

32.2k views Asked by At

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

10

There are 10 answers

2
Eugen Constantin Dinca On BEST ANSWER

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
0
DPD On

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

2
Billy ONeal On

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).

0
ClosureCowboy On

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.

0
Mohsen Mesgarpour On

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

7
Matthieu M. On

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

2
xaviersjs On

The using keyword can be used to change visibility

struct A
{
    void method1();
};

struct B: public A
{
    void method2();

    private:
    using A::method1;
};
1
CodeBricks On

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.

0
It'sPete On

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.

0
Alexander Novinskiy On

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.