简体   繁体   English

隐藏儿童功能

[英]Hiding functions from children

I would like some children (inheriting classes) to not see certain work functions that are in the Parent class. 我希望某些孩子(继承类)看不到Parent类中的某些工作功能。 I understand that making these private would mean that the children cannot use these functions but the thing is that they would see them. 我了解将这些设置为私有意味着孩子们无法使用这些功能,但事实是他们会看到它们。 I am trying to avoid the issue of having a bunch of "junk" show up in auto-complete. 我试图避免在自动完成中出现一堆“垃圾”的问题。

With the above in mind, I have come up with an idea. 考虑到以上几点,我想出了一个主意。 Code below. 下面的代码。 The thing is that I am not entirely sure what the nature of secretFunc is. 关键是我不确定secretFunc的本质是什么。 Is this a global function or does it belong to the Parent class in some way? 这是全局函数还是它在某种程度上属于Parent类? It is not declared in the header, it is just defined in the cpp. 它没有在标头中声明,而是在cpp中定义。 The idea is that I could have some work functions like this in the Parent and then these would be hidden from the Child class. 我的想法是,我可以在Parent中拥有一些这样的工作功能,然后将其从Child类中隐藏。 Is a more elite way to do this? 是一种更出色的方法吗? Even if there is, I would still like to understand the nature of secretFunc. 即使有,我仍然想了解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.

What you get with secretFunc() is essentially the opposite of what you get with privateFunc() . 你得到的与secretFunc()本质上是你得到了什么相反privateFunc() That is: 那是:

  • privateFunc() is visible but not accessible (nothing but other Parent methods can call it). privateFunc()是可见的,但不可访问(只有其他Parent方法可以调用它)。
  • secretFunc() is not visible, but is accessible. secretFunc()不可见,但可以访问。

To elaborate, a free function defined like secretFunc() is in the global namespace, even though there is no declaration available in the header file. 详细说来,一个定义为secretFunc()的自由函数位于全局名称空间中,即使头文件中没有可用的声明。 So code in any other file that is linked with Parent.cpp would be able to call secretFunc() by writing their own declaration, so long as it is correct. 因此,只要正确,与Parent.cpp链接的任何其他文件中的代码都可以通过编写自己的声明来调用secretFunc()

That is, Child.cpp could contain 也就是说, Child.cpp可能包含

void secretFunc();

At the top, which makes the function visible, and then anything in Child.cpp could call secretFunc() . 在顶部,使该函数可见,然后Child.cpp任何内容Child.cpp可以调用secretFunc()

If all you're trying to do is make the function invisible to autocomplete, then this may not be a concern. 如果您要做的只是使该函数对自动完成不可见,则可能不必担心。 But you can achieve both invisibility and inaccessibility at once. 但是您可以同时实现隐身性和隐身性。 What you need to do is remove secretFunc from the global namespace. 您需要做的是从全局名称空间中删除secretFunc You can do that by enclosing it in an anonymous namespace. 您可以通过将其包含在匿名名称空间中来实现。

So in Parent.cpp you write: 因此,在Parent.cpp您可以编写:

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

This makes the function both invisible and inaccessible to anything outside the Parent.cpp file. 这使得该函数对于Parent.cpp文件之外的任何内容都是不可见和不可访问的。 If Child.cpp were to make its own declaration (as described above), the linker would produce an error because it would not be able to find a function with the secretFunc name in the global namespace. 如果Child.cpp做出自己的声明(如上所述),则链接器将产生错误,因为它无法在全局名称空间中找到具有secretFunc名称的函数。

Note that this is different from a private method, in to ways: 请注意,这与私有方法的不同之处在于:

  • The accessibility is limited to things in the Parent.cpp file , not the Parent class . 可访问性仅限于Parent.cpp 文件中的内容 ,而不是Parent
  • Because it is not a class member of Parent , it has no special access into Parent objects (and doesn't have a this pointer). 因为它不是Parent的类成员,所以它没有对Parent对象的特殊访问权限(并且没有this指针)。

One final thing. 最后一件事。 Using the static keyword instead of enclosing the function in an anonymous namespace has the same effect, but this is a C-ism. 使用static关键字而不是将函数包含在匿名名称空间中具有相同的效果,但这是C-ism。 Using the anonymous namespace is the idiomatic C++ way to do it. 使用匿名名称空间是惯用的C ++方法。

The secretFunc is a stand-alone function which can be called by anybody who sees it or its declaration. secretFunc是一个独立的函数,任何看到该函数或其声明的人都可以调用该函数。 It is different from class methods in that it has no access to members of the class instance which calls it. 它与类方法的不同之处在于,它无法访问调用它的类实例的成员。

For your question about hiding private member functions from auto complete, it depends on your IDE, but if you're using Visual Studio it looks like it isn't possible . 对于您是否要隐藏自动完成的私有成员函数的问题,这取决于您的IDE,但是如果您使用的是Visual Studio,那似乎是不可能的 If you're using Qt Creator, it also looks like it isn't possible . 如果您使用的是Qt Creator,它似乎也是不可能的 I am unsure of Eclipse, but I suspect it's not possible as well. 我不确定Eclipse,但我怀疑这也是不可能的。 When I say "not possible," I mean not possible without changing your code. 当我说“不可能”时,我的意思是不更改代码就不可能。 The pimpl idiom can be used to hide private members as well as external dependencies. pimpl习惯用法可用于隐藏私有成员以及外部依赖项。 Of course, your private pimpl will still be visible by auto complete, but it would be an incomplete pointer type, so it's not much use to the user, and it's only one member. 当然,您的private pimpl仍然可以通过自动完成看到,但是它将是不完整的指针类型,因此对用户来说并没有太大用处,它只是一个成员。

For your question about secretFunc , if you make secretFunc static , then only Parent.cpp will be able to see and use it. 对于有关secretFunc的问题,如果将secretFunc static ,则只有Parent.cpp可以查看和使用它。 As it currently is, any other source file can say extern void secretFunc(); 就目前而言,任何其他源文件都可以说extern void secretFunc(); and then start using secretFunc . 然后开始使用secretFunc

If you give it the static modifier ( static void secretFunc() ), then it can only be seen by the source file its in. The linker won't expose it to other translation units. 如果为它提供了static修饰符( static void secretFunc() ),则它只能在源文件的in中看到。链接器不会将其公开给其他翻译单元。

You can have private virtual functions, and you can override (but not call) them in derived classes. 您可以具有私有虚拟函数,并且可以在派生类中重写(但不能调用)它们。 This language feature is, as they say, widely known in narrow circles. 正如他们所说,这种语言功能在狭窄的圈子中广为人知。 People are using it in production code. 人们在生产代码中使用它。

So it would seem that hiding private members from IDEs is counterproductive. 因此,似乎将私有成员隐藏在IDE中会适得其反。

In VS, you can hide any member from IntelliSense using a little preprocessor trick: 在VS中,您可以使用一些预处理器技巧从IntelliSense中隐藏任何成员:

#ifndef __INTELLISENSE__    
void ThisShouldNotBeSeen() {}
#endif

but this will hide it from IntelliSense everywhere, not just in derived classes. 但这会将其隐藏在所有地方的IntelliSense中,而不仅仅是在派生类中。 This is inconvenient when developing the parent class itself, as you get lots of spurious IntelliSense errors and red underlines. 在开发父类本身时,这很不方便,因为您会收到很多虚假的IntelliSense错误和红色下划线。 It could be useful to add this macro to header files you release. 将此宏添加到您发布的头文件中可能会很有用。

I'm not sure about other IDEs. 我不确定其他IDE。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM