对子级隐藏函数

Hiding functions from children

本文关键字:函数 隐藏      更新时间:2023-10-16

我希望一些子级(继承类)不要看到Parent类中的某些工作函数。我知道,将这些功能私有化意味着孩子们不能使用这些功能,但问题是他们会看到它们。我正在努力避免在自动完成中出现一堆"垃圾"的问题。

考虑到以上情况,我想出了一个主意。下面的代码。问题是,我不完全确定secretFunc的性质。这是一个全局函数还是在某种程度上属于Parent类?它没有在标头中声明,只是在cpp中定义。这个想法是,我可以在Parent中有一些这样的工作函数,然后这些函数将从Child类中隐藏。这是一种更精英的方式吗?即使有,我仍然想了解secretFunc的本质。

#ifndef PARENT_H
#define PARENT_H
class Parent
{
public:
Parent();
~Parent();
private:
void privateFunc();
protected:
void protectedFunc();
public:
void publicFunc();
};
#endif

#include "Parent.h"
//What is the nature of this function???
void secretFunc()
{
}
UnitTest::UnitTest()
{
}
UnitTest::~UnitTest()
{
}
void UnitTest::privateFunc()
{
}
void UnitTest::protectedFunc()
{
}
void UnitTest::publicFunc()
{
}

#ifndef CHILD_H
#define CHILD_H
#include "Parent.h"
class Child : public Parent
{
public:
Child();
~Child();
};
#endif

#include "Child.h"
UnitTest::Child()
{
}
UnitTest::~Child()
{
}
//Auto complete can see private Parent functions!
//Of course, child can't use them, but it can see them.
//I wish to hide these private functions from child.
//Auto complete can see and can also use protected Parent funcitons.
//As should be...
//Auto complete can see and can also use public Parent funcitons.
//As should be...
//secetFunc should be invisible.

使用secretFunc()得到的基本上与使用privateFunc()得到的相反。即:

  • privateFunc()可见但不可访问(只有其他Parent方法才能调用它)
  • secretFunc()不可见,但可以访问

详细说明,像secretFunc()这样定义的自由函数在全局命名空间中,即使头文件中没有可用的声明。因此,任何其他与Parent.cpp链接的文件中的代码都可以通过编写自己的声明来调用secretFunc(),只要声明是正确的。

也就是说,Child.cpp可能包含

void secretFunc();

在顶部,这使函数可见,然后Child.cpp中的任何东西都可以调用secretFunc()

如果您所要做的只是使函数对自动完成不可见,那么这可能不是一个问题。但你可以同时实现隐形和不可接近。您需要做的是从全局命名空间中删除secretFunc。您可以通过将它封装在一个匿名命名空间中来实现这一点。

所以在Parent.cpp中,您写道:

namespace {
void secretFunc() {
// ...
}
}

这使得函数对于Parent.cpp文件之外的任何东西都是不可见和不可访问的。如果Child.cpp进行自己的声明(如上所述),链接器将产生错误,因为它将无法在全局命名空间中找到具有secretFunc名称的函数。

注意,这与私有方法的不同之处在于:

  • 可访问性仅限于Parent.cpp文件中的内容,而不是Parent
  • 因为它不是Parent的类成员,所以它对Parent对象没有特殊访问权限(也没有this指针)

最后一件事。使用static关键字而不是将函数封装在匿名命名空间中具有相同的效果,但这是一种C-ism。使用匿名名称空间是惯用的C++方法

secretFunc是一个独立的函数,任何看到它或它的声明的人都可以调用它。它与类方法的不同之处在于,它不能访问调用它的类实例的成员

对于您关于隐藏私有成员函数以防止自动完成的问题,这取决于您的IDE,但如果您使用的是Visual Studio,这似乎是不可能的。如果你正在使用Qt Creator,它看起来也是不可能的。我不确定Eclipse,但我怀疑它也不可能。当我说"不可能"时,我的意思是不更改代码就不可能。皮条习惯用法可以用来隐藏私有成员以及外部依赖关系。当然,您的private pimpl在自动完成时仍然可见,但它将是一个不完整的指针类型,因此它对用户没有多大用处,而且它只是一个成员。

对于您关于secretFunc的问题,如果您将secretFunc设为static,那么只有Parent.cpp才能看到并使用它。按照目前的情况,任何其他源文件都可以说extern void secretFunc();,然后开始使用secretFunc

如果你给它static修饰符(static void secretFunc()),那么它只能被它的源文件看到。链接器不会将它暴露给其他翻译单元。

您可以拥有私有虚拟函数,并且可以在派生类中重写(但不能调用)它们。正如他们所说,这种语言特征在狭隘的圈子里广为人知。人们正在生产代码中使用它。

因此,向IDE隐藏私人成员似乎会适得其反。

在VS中,您可以使用一个小的预处理器技巧来向IntelliSense隐藏任何成员:

#ifndef __INTELLISENSE__    
void ThisShouldNotBeSeen() {}
#endif

但这将在任何地方对IntelliSense隐藏它,而不仅仅是在派生类中。这在开发父类本身时很不方便,因为您会得到很多虚假的IntelliSense错误和红色下划线。将此宏添加到您发布的头文件中可能会很有用。

我不确定其他IDE。