способ в C ++ скрыть определенную функцию - PullRequest
18 голосов
/ 05 февраля 2011

У меня есть наследство struct A : public B, я хочу скрыть отдельные функции от B, это возможно?

я знаю, что обратное возможно при использовании using BMethod в объявлении А.

ура

Ответы [ 10 ]

42 голосов
/ 05 февраля 2011

Если вы хотите выборочно скрывать функции от B, в первую очередь не имеет смысла использовать публичное наследование.
Используйте личное наследование и выборочно перенесите методы из B в область 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
25 голосов
/ 05 февраля 2011

Здесь есть проблема: это будет прямым нарушением принципа подстановки Лискова, а именно: A не будет действовать как B.

Если вы хотите повторно использовать реализацию B, решение заключается в следующем:

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

private:
  B b;
};

Не злоупотребляйте наследованием, используйте вместо этого композицию

11 голосов
/ 31 октября 2014

Помимо способов, описанных в предыдущих ответах - состав, частное наследование и не приватное наследование, но с унаследованным методом, объявленным закрытым, - еще один способ явно delete унаследованный метод:

#include <iostream>

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

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

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

Хотя вызов b.foo() вызывает ошибку компилятора, клиентский код все равно может вызвать версию базового класса, указав идентификатор базового класса A:

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

Этот явный способ удаления работает, когда foo is not виртуальный не удаленный метод в A.Согласно стандарту C ++ 11 §10.3 / 16, это явное удаление некорректно, когда удаленный метод в производном классе переопределяет виртуальный не удаленный метод базового класса.Для получения дополнительной информации об этом ограничении см. Ответы на вопрос SO C ++ 11 Удалить переопределенный метод .

8 голосов
/ 05 февраля 2011

Вы не можете "скрыть это" как таковое, но вы можете сделать это ошибкой во время компиляции, чтобы вызвать его.Пример:

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;
}

Примеры на кодовой панели с ошибкой и без .

Несмотря на то, что это возможно, вы действительноне должен этого делать.Вы запутаете клиентов до чертиков.

РЕДАКТИРОВАТЬ: Обратите внимание, что вы также можете сделать это с виртуальными функциями с ошибкой ).

4 голосов
/ 06 июня 2013

Для тех, кто предлагает композицию ... это может быть не самым лучшим способом достижения цели. Насколько я понимаю, принцип подстановки Лискова гласит, что есть возможность использования функций из базового класса для ребенка, а не то, что они обязательно должны быть. Например, для определенного базового класса у вас может быть несколько функций, которые по существу выполняют одну и ту же операцию, но для разных конкретных случаев. В производном классе вы можете абстрагировать эти общедоступные функции в пользу упрощения интерфейса пользователя. Это где частное наследование может быть использовано. Частное наследование также может быть необходимым, если у нас есть защищенные функции в базовом классе, которые мы не хотим, чтобы пользователь базового класса вызывал, но при этом были бы неоценимы для производного класса.

Короче говоря, если вам нужно, используйте частное наследование, но в большинстве случаев предпочтительным является состав.

3 голосов
/ 01 декабря 2018

Ключевое слово using можно использовать для изменения видимости

struct A
{
    void method1();
};

struct B: public A
{
    void method2();

    private:
    using A::method1;
};
3 голосов
/ 14 февраля 2018

Существует еще один подход.

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

Использование BInterface в качестве фильтра для унаследованных классов для исключения нежелательных методов.Принцип подстановки Лискова в этом случае не нарушается, поскольку объект класса BInterface не является объектом класса A, даже если объект класса B является объектом класса BInterface.

2 голосов
/ 05 февраля 2011

Если методы являются частными в B, то они останутся скрытыми, даже если вы используете публичное наследование.

0 голосов
/ 05 февраля 2011

Почему бы вам не сделать его виртуальным в базовом классе и не переопределить его в дочерних элементах?( дополнительная помощь )

0 голосов
/ 05 февраля 2011

Невозможно изменить видимость исходного метода.

Вы можете создать метод в структуре A с тем же именем и сделать этот метод закрытым, но это не мешает вызову метода, когда на экземпляр структуры A ссылается переменная тип B.

...