2011-04-14 230 views
22

(在C++中)我有一个类,其结构在头文件中声明。该头文件包含在很多源文件中,这样当我编辑它时,我需要重新编译大量文件。避免在类头文件中声明私有函数(C++)

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

我该如何做到这一点?

+0

如果我从头开始编写这个类,有些方法可以很好地工作。但是,我并非从头开始,这个班已经写好了。 – user664303 2011-04-16 09:11:55

回答

4

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

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); 
} 
+0

这是我迄今为止的理解,但我不是100%确定的。感谢收到的评论。 – user664303 2011-04-16 09:39:00

+0

你在'class Foo'中仍然有'int var'。问题的整个目的是将它移到'class FooImpl'? – balki 2013-03-06 13:04:58

+1

@balki:不,这个问题的关键在于如何在不改变标题的情况下在课堂中添加或编辑私人_函数_。如果我将私有变量移动到FooImpl,那么我还必须将所有现有的公共函数转发给该类。看到我对Erik关于这个问题的答案的第一个评论。 – user664303 2013-03-07 10:51:48

14

使用pImpl idiom - 您的可见类保留一个指向实际类,并将呼叫转发给公共成员函数。

编辑:在回应评论

// 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应该有FooImpl公众成员的副本和简单的转发调用这些。所有用户将只包含“Foo.h” - 您可以更改FooImpl的所有私人详细信息,而Foo的用户看不到任何更改。

+0

谢谢。一般而言,这是个好主意。然而,在这种情况下,我并没有开始使用这个框架,所以转向它需要对我的类进行大量的重写,包括为它的所有公共函数编写包装。我希望能够将标题中的一部分私有函数发送出去,没有太多麻烦。 – user664303 2011-04-14 15:32:53

+0

@ user664303:继承*可能是一个解决方案 - 这个特殊的问题是C++ imo令人讨厌的谬误之一。 – Erik 2011-04-14 15:37:50

+0

我是否认为它必然需要类实例指针的转换,例如:((priv_class *)this) - > priv_func();.或者有什么办法可以避免这种情况? – user664303 2011-04-14 16:13:15

1

创建一个抽象基类仅包含公共职能,并在你的标题参考这一点。创建你的真实课程作为其他地方的实施。只有需要创建类的源文件需要查看实现类头。