C++ 中隐藏特定函数的方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4908539/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
a way in c++ to hide a specific function
提问by lurscher
i have an inheritance struct A : public B
, i want to hide individual functions from B, is this possible?
我有一个继承struct A : public B
,我想对 B 隐藏单个函数,这可能吗?
i know the opposite is possible using using BMethod
in the A declaration.
我知道using BMethod
在 A 声明中使用相反的情况是可能的。
cheers
干杯
采纳答案by xaviersjs
The using
keyword can be used to change visibility
该using
关键字可以用来改变的可视性
struct A
{
void method1();
};
struct B: public A
{
void method2();
private:
using A::method1;
};
回答by Eugen Constantin Dinca
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:
如果您想有选择地对 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
回答by Matthieu M.
There is an issue here: this would be a direct violation of the Liskov Substitution Principle, namely A
would not act as aB
any longer.
这里有一个问题:这将直接违反 Liskov 替换原则,即A
不再充当 aB
。
If you wish to reuse B
implementation, the solution is simply to do so:
如果您希望重用B
实现,解决方案很简单:
class A
{
public:
void foo() { return b.foo(); }
void bar() { return b.bar(); }
// ...
private:
B b;
};
Don't abuse inheritance, use composition instead
不要滥用继承,改用组合
回答by CodeBricks
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:
除了前面答案中描述的方法——组合、私有继承和非私有继承但继承的方法声明为私有——另一种方法是显式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
}
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.foo()
调用会产生编译器错误,但客户端代码仍然可以通过使用基类标识符进行限定来调用基类的版本A
:
b.A::foo(); // compiles, outputs 'foo' to console
This explicit deletion way works when foo
is nota 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.
当这种显式删除的工作方式foo
是不是在一个虚拟的非删除方法A
。根据 C++11 标准 §10.3/16,当派生类中的已删除方法覆盖基类的虚拟未删除方法时,此显式删除是格式错误的。有关此限制的更多信息,请参阅 SO 问题C++11 删除覆盖方法的答案。
回答by Billy ONeal
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).
回答by It'sPete
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.
对于那些建议组合的人......这可能不是处理事情的最佳方式。我的理解是,Liskov 替换原则仅说明基类中的函数有可能用于子类,而不是它们一定应该使用。例如,对于特定的基类,您可能有多个函数,它们基本上执行相同的操作,但针对不同的特定情况。在派生类中,您可能希望将这些公共函数抽象出来以简化用户界面。这是可以使用私有继承的地方。私有继承也可能是必要的,如果我们在基类中有我们不希望基类的用户调用的受保护的函数,但对于派生类来说是无价的。
In short, if you HAVE to, use private inheritance, but composition is preferred in most cases.
简而言之,如果必须,请使用私有继承,但在大多数情况下首选组合。
回答by Alexander Novinskiy
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.
使用 BInterface 作为继承类的过滤器以排除不需要的方法。在这种情况下,不违反 Liskov 替换原则,因为 BInterface 类的对象不是 A 类的对象,即使 B 类的对象是 BInterface 类的对象。
回答by DPD
If the methods are private in B, then they will remain hidden to a even if you use public inheritance.
如果方法在 B 中是私有的,那么即使您使用公共继承,它们也会对 a 保持隐藏状态。
回答by ClosureCowboy
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
.
您可以在 struct 中创建一个A
具有相同名称的方法并将该方法设为私有,但这并不能阻止当 struct 的实例A
被类型变量引用时调用该方法B
。