可以将基类的单个成员的状态更改为private吗?
Can I change the status of individual members of a base class to private?
我正在使用wxWidgets,如果您曾经使用过它,您将知道在基类中有许多公共函数。我最近遇到了一种情况,我不希望从派生类直接调用方法SetText()
。也就是说,派生类继承了SetText()
函数,但我不希望这个函数对客户端可用。相反,我提供了两个调用SetText()
的新函数,但不是在执行一些额外的操作之前。
目前,客户端(我!)可以忘记调用特殊函数,只需调用SetText()
。因此,一些额外的操作将不会被执行。这些操作非常微妙,很容易被忽略。
那么,我可以将单个函数标记为私有的,这样客户端就不可能调用它们,或者简单地使客户端不可能直接调用它(他们将不得不使用我的函数来间接调用它)?
注意SetText()
是而不是虚拟的。
EDIT:对于将来遇到这个问题的程序员,请检查标记的答案和Doug T。的答案。
实际上有两种方法可以做到这一点。Doug T.对第一种方法做了一个很好的概述——使用私有/受保护的继承和组合——所以我就不深入讨论了。
使用私有/受保护继承的问题是它掩盖了所有的内容。然后,您必须有选择地公开您仍然希望公开的成员。如果你想让所有的事情都公开,并且只想掩盖其中的一件事,那么这可能会成为一个令人头疼的问题。这就需要第二种方法来实现这一点——使用using
关键字。
例如,在您的例子中,您可以简单地如下声明您的类:
class Child : public Parent
{
//...
private:
using Parent::SetText; // overrides the access!
};
这个只有掩码SetText方法!
请记住,指向Child
的指针总是可以转换为指向Parent
的指针,并且可以再次访问该方法-但这也是继承的问题:
class Parent
{
public:
void SomeMethod() { }
void AnotherMethod() { }
};
class ChildUsing : public Parent
{
private:
using Parent::SomeMethod;
};
class ChildPrivateInheritance : private Parent
{
};
void main()
{
Parent *p = new Parent();
ChildUsing *a = new ChildUsing();
ChildPrivateInheritance *b = new ChildPrivateInheritance();
p->SomeMethod(); // Works just fine
a->SomeMethod(); // !! Won't compile !!
a->AnotherMethod(); // Works just fine
((Parent*)a)->SomeMethod(); // Compiles without a problem
b->SomeMethod(); // !! Won't compile !!
b->AnotherMethod(); // !! Won't compile !!
((Parent*)b)->SomeMethod(); // Again, compiles fine
delete p; delete a; delete b;
}
试图访问ChildUsing
实例上的SomeMethod
会产生(在VS2005中):
error C2248: 'ChildUsing::SomeMethod' : cannot access private member declared in class 'ChildUsing'
然而,在ChildPrivateInheritance
的实例上访问SomeMethod
或 AnotherMethod
会产生:
error C2247: 'Parent::SomeMethod' not accessible because 'ChildPrivateInheritance' uses 'private' to inherit from 'Parent'
-
你可以通过私有继承将每个 public设置为private,并公开你想要的接口。
class YourWidget : private BaseClass { }; YourWidget widget; widget.SetText(); // this is private
这阻止了您遍历基类,并破坏了"is-a"关系。以下代码无法编译:
BaseClass* ptr = new YourWidget(); //error, no conversion available
它也影响了
BaseClass
的每个公共成员,我不确定它是否适合wxWidgets的工作方式。 -
您可以通过在派生类中创建私有版本来隐藏
SetText
。这仅在通过派生类指针访问时有效,并且在通过基类指针访问时不提供任何安全性。如果客户端有基类ptr,则仍然会调用基类SetText
。 -
您可以包装
BaseClass
,而不是从它派生,并公开您想要的接口。这可能是可能的,也可能是不可能的,这取决于代码的工作方式。如果你想要正常的接口,但稍微改变一下,那么你就必须重新实现你想要转发到BaseClass
的每个功能。 -
你可以让
YourWidget
从第二个接口继承,这个接口提供了你想要暴露给你的代码的接口,并传递指针到这个接口,而不是指针到你的BaseClass
。例如class IMyWidget { public: virtual void SpecialSetText() = 0; } class YourWidget : public BaseClass, public IMyWidget { public: void SpecialSetText() {/*use SetText in a special way*/} };
然后在你的代码中,你可以传递
IMyWidget
指针而不是BaseClass
/YourWidget
指针。这为代码的特定部分提供了一个进入YourWidget
的特定接口,并防止(禁止向下转换)接口的其他部分被使用。
根据您希望通过派生类拥有的访问权限,您可以使用私有(或受保护)继承,这将不允许非友类访问继承的成员/方法,或者通过在派生类中声明一个新方法来隐藏基方法,该方法要么重定向,要么(如果您需要额外的参数或其他)错误
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 助记符和指向成员语法的指针
- 用于访问容器<T>数据成员的正确 API
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- "class::data member is private"错误,但我正在使用成员函数对其进行操作?
- 是否可以通过在单元测试中定义我自己的 PRIVATE 宏来使私有成员公开
- 为什么即使将成员函数声明为 "private",仍然可以访问它?
- 为什么 PRIVATE 成员函数不能是另一个类的友元函数?
- 使用OpenGL将结构体加载到成员为Private的VBO中
- 为什么在使用类成员访问其他类的私有成员时出现"is private"错误?
- 在OOP中,Private成员对于谁是私有的
- 友元成员函数无法访问private成员
- C++。无法调用成员函数。错误 : "foo is private"
- 可以将基类的单个成员的状态更改为private吗?
- 模板友元函数无法访问private成员
- 可以将c++类的所有成员(包括数据和函数)定义为private吗?