【问题标题】:Calling private functions in nested classes在嵌套类中调用私有函数
【发布时间】:2013-12-17 16:47:41
【问题描述】:

我开发了一个类,我们称之为 foo。在头文件中,我选择在 private: 部分中包含一个包含 foo 的所有私有成员的类。这样,如果我必须编辑 foo 的任何私有成员,我就不必重新编译每个使用 foo.h 的源文件。它是这样设置的:

#ifndef FOO_H
#define FOO_H

class fooData;

class foo
{
   private:
      fooPrivate *prv; // This class stores foo's private members
   public:
      foo(); // Default constructor
      void bar();
}

#endif

我的 foo.cpp 类如下所示:

#include "foo.h"

class fooPrivate // Class which stores foo's private members
{
   public:
      void doMagic();
}

foo::foo()
{
   prv = new fooPrivate; // Instantiate fooPrivate
   prv->doMagic();
}

void foo::magic() // This is a public member function of foo
{
   std::cout << "Magic!" << std::endl;
}

void fooPrivate::doMagic() // This is a function of private member fooPrivate
{
   magic(); // I want to call a public member of foo here
}

你们中的大多数人已经知道我尝试从 doMagic() 调用 magic() 会导致的错误:

error: 'magic' was not declared in this scope

而且,更改对 foo::magic() 的调用会导致:

error: cannot call member function 'void foo::magic()' without onject

现在,我真的很想避免在 fooPrivate 类型的对象内实例化 foo 类型的对象,它本身是由 foo 类型的对象的实例化产生的......那么,有没有办法调用 public 来自 fooPrivate 的公共成员函数的成员函数 magic()?

【问题讨论】:

    标签: c++


    【解决方案1】:

    创建 fooPrivate 时,传入对 foo 的引用作为构造函数的一部分:

    foo::foo()
    {
      prv= new fooPrivate( * this) ;
    }
    
    class fooPrivate
    {
      foo & foo_ ;
      ...
    }
    
    fooPrivate::fooPrivate( foo & aparen) : foo_( aparen ) { }
    

    然后在doMagic() 中通过引用调用它:

    void fooPrivate::doMagic()
    {
      foo_.magic() ;
    }
    

    另外,将 fooPrivate 存储在 unique_ptr 中,这样当 foo 被销毁时,fooPrivate 也会随之销毁:

    class foo
    {
      private:
        std::unique_ptr<fooPrivate> prv ;
    

    为方便起见,您可以像这样初始化:

    foo::foo() : prv( new fooPrivate( * this ) ) { }
    

    顺便说一句,我不建议在构造函数中调用prv-&gt;magic(),如果它会通过调用doMagic 回调到仍在创建的foo

    【讨论】:

    • 在实施您的解决方案时,我遇到了“错误:类 'fooPrivate' 没有任何名为 'foo_' 的字段。”将“foo foo_”声明添加到 fooPrivate 会导致编译成功,但在运行时也会出现段错误。编辑:我可能知道原因,如果没有,我会回复你。
    • 抱歉我要发布定义的那部分,让我编辑一下。
    • 修复了它。很好的解释和非常巧妙的技巧。您可能希望进一步编辑您的解决方案,在“foo & foo_;”之后添加一个右大括号,在“...”之前添加一个右大括号,因为没有它,您似乎表示“fooPrivate::fooPrivate(foo & aparen): foo_( aparen ) { }" 位于类定义中。没有能力的编码人员会误会您的指示,但是遇到您的解决方案的新手可能会感到困惑。
    • 我很想在某个地方检查我的测试文件(我在发布之前检查了我的语法),但最后没有。很高兴您完成了实施。
    猜你喜欢
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 2023-04-07
    • 2017-02-10
    • 2012-09-14
    • 1970-01-01
    相关资源
    最近更新 更多