Способ в C++ скрыть определенную функцию
У меня есть наследство struct A : public B
Я хочу скрыть отдельные функции от B, это возможно?
я знаю обратное возможно с помощью using BMethod
в декларации.
ура
10 ответов
Здесь есть проблема: это будет прямым нарушением принципа подстановки Лискова, а именно A
не будет действовать как B
больше
Если вы хотите использовать повторно B
реализация, решение просто сделать так:
class A
{
public:
void foo() { return b.foo(); }
void bar() { return b.bar(); }
// ...
private:
B b;
};
Не злоупотребляйте наследованием, вместо этого используйте композицию
Если вы хотите выборочно скрывать функции от 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
using
Ключевое слово может быть использовано для изменения видимости
struct A
{
void method1();
};
struct B: public A
{
void method2();
private:
using A::method1;
};
Помимо способов, описанных в предыдущих ответах - составление, частное наследование и не приватное наследование, но с унаследованным методом, объявленным закрытым, - еще один способ заключается в явном 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
не является виртуальным не удаленным методом в A
, Согласно стандарту C++11 §10.3/16, это явное удаление некорректно, когда удаленный метод в производном классе переопределяет виртуальный не удаленный метод базового класса. Для получения дополнительной информации об этом ограничении см. Ответы на вопрос SO C++11 Delete Overriden Method.
Вы не можете "скрыть это" как таковое, но вы можете сделать это ошибкой во время компиляции, чтобы вызвать его. Пример:
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;
}
Примеры на кодовой панели с ошибкой и без.
Тем не менее, несмотря на то, что это возможно, вы действительно не должны этого делать. Вы запутаете клиентов.
РЕДАКТИРОВАТЬ: Обратите внимание, что вы также можете сделать это с виртуальными функциями (и с ошибкой).
Есть еще один подход.
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.
Для тех, кто предлагает композицию... это может быть не самым лучшим способом достижения цели. Насколько я понимаю, принцип подстановки Лискова гласит, что есть возможность использования функций из базового класса для ребенка, а не то, что они обязательно должны быть. Например, для определенного базового класса у вас может быть несколько функций, которые по существу выполняют одну и ту же операцию, но для разных конкретных случаев. В производном классе вы можете абстрагировать эти общедоступные функции в пользу упрощения интерфейса пользователя. Это где частное наследование может быть использовано. Частное наследование также может быть необходимым, если у нас есть защищенные функции в базовом классе, которые мы не хотим, чтобы пользователь базового класса вызывал, но при этом были бы неоценимы для производного класса.
Короче говоря, если вам нужно, используйте частное наследование, но в большинстве случаев предпочтительным является состав.
Если методы являются частными в B, то они останутся скрытыми, даже если вы используете публичное наследование.
Почему бы вам не сделать его виртуальным в базовом классе и не переопределить его в дочерних элементах? ( дополнительная помощь)
Невозможно изменить видимость исходного метода.
Вы можете создать метод в структуре A
с тем же именем и иметь этот метод быть закрытым, но это не мешает вызывать метод, когда экземпляр структуры A
на него ссылается переменная типа B
,