避免在类头文件中声明私有函数 (C++)

Posted

技术标签:

【中文标题】避免在类头文件中声明私有函数 (C++)【英文标题】:Avoiding declaring private functions in class header files (C++) 【发布时间】:2011-08-05 15:31:50 【问题描述】:

(在 C++ 中)我有一个类,其结构在头文件中声明。该头文件包含在很多源文件中,因此当我编辑它时,我需要重新编译很多文件。

该类具有一组仅在一个源文件中调用的私有函数。目前它们在头文件的类结构中声明。当我添加这种类型的新函数或编辑参数时,它会导致重新编译大量文件。我想在其他地方声明这些函数,这样只有定义和调用它们的文件被重新编译(以节省时间)。不过,它们仍然需要能够访问内部类变量。

我怎样才能做到这一点?

【问题讨论】:

如果我从头开始编写课程,有些方法效果很好。但是,我不是从头开始。这个类已经写好了。 【参考方案1】:

创建一个只包含公共函数的抽象基类,并在你的头文件中引用它。创建您的真实类作为其他地方的实现。只有需要创建类的源文件才需要查看实现类头。

【讨论】:

【参考方案2】:

没有办法在主类声明之外声明类的成员函数。因此,如果您想在所讨论的类之外声明可以访问该类特定实例的成员变量的函数,那么除了将该实例传递给函数之外,我别无选择。此外,如果您希望函数能够访问私有变量和受保护变量,您需要将它们放在一个新类中,并使原始类成为它的朋友。例如

header.h:

class FooImpl;

class Foo 
public:
   int bar();
   friend class FooImpl;
private:
   int var;

impl.cpp:

#include "header.h"

class FooImpl 
public:
   int bar(Foo &);


int FooImpl::bar(Foo &foo) 
return foo.var;


int Foo::bar() 
return FooImpl::bar(*this);

【讨论】:

这是我目前的理解,但我不是 100% 确定。非常感谢您的意见。 您在class Foo 中还有int var。问题的重点不就是把它移到class FooImpl吗? @balki:不,这个问题的重点是如何在类中添加或编辑私有函数,而不更改标题。如果我将私有变量移动到 FooImpl,那么我还必须将所有现有的公共函数转发到该类。请参阅我对 Erik 的回答的第一条评论。【参考方案3】:

使用pImpl idiom - 您的可见类保留一个指向真实类的指针并将调用转发到公共成员函数。

编辑:响应 cmets

// Foo.h:

class FooImpl; // Do *not* include FooImpl.h
class Foo 
public:
  Foo();
  ~Foo();
  //.. also need copy ctor and op=
  int bar();
private:
  FooImpl * Impl;
;

// FooImpl.h:

class FooImpl 
public:
  int bar()  return Bar; 
private:
  int Bar;
;

// Foo.cpp:

#include "FooImpl.h"

Foo::Foo()  Impl = new FooImpl(); 
Foo::~Foo()  delete Impl; 
int Foo::bar()  return Impl->bar(); 

将你的类的实际实现保存在FooImpl - Foo 应该有FooImplpublic 成员的副本,然后简单地将调用转发给这些成员。所有用户将仅包含“Foo.h” - 您可以更改 FooImpl 的所有私人详细信息,而 Foo 的用户不会看到任何更改。

【讨论】:

谢谢。总的来说,这是一个好主意。但是,在这种情况下,我并没有开始使用这个框架,所以转向它需要对我的类进行大量重写,包括为其所有公共函数编写包装器。我希望能够从标头中发送一部分私有函数,而不需要太多麻烦。 @user664303:继承可能是一种解决方案——这个特殊问题是 C++ imo 令人讨厌的谬误之一。 我是否认为它必然需要类实例指针的转换,例如:((priv_class *)this)->priv_func();。或者有没有办法避免这种情况? @user664303:前向声明 - .h:class FooImpl; class Foo public: void bar(); FooImpl * Impl; ;.cpp:#include "FooImpl.h" ... void Foo::bar() Impl->bar(); @Erik:我不明白 FooImpl::bar() 如何访问 Foo 的私有成员。我可以让 Foo 成为 FooImpl 的朋友,但我仍然必须向 FooImpl::bar() 传递一个指向 Foo 实例的指针。【参考方案4】:

您是否在寻找 Compiler Firewall,又名 PIMPL?

【讨论】:

以上是关于避免在类头文件中声明私有函数 (C++)的主要内容,如果未能解决你的问题,请参考以下文章

C++语法

C++学习_类与对象

如何在另一个类头文件中定义类构造函数?

如何初始化已经在 C++ 中声明的唯一锁?

Friend函数访问静态库中定义的类的私有成员

C++ - 使用 Visual Studio 声明成员函数