【问题标题】:How do I access a private constructor in a separate class?如何在单独的类中访问私有构造函数?
【发布时间】:2013-09-13 07:40:11
【问题描述】:

我正在用 C++ 编写一个库。我的图书馆有两个课程,AB。我想从任何引用我的库的代码中隐藏 A() 构造函数。我还希望 B 类能够调用 A() 构造函数。

我来自 C# 背景,几乎不记得我的 C++。在 C# 中,我只需将 A() 构造函数声明为 internal。我读过在 C++ 中最接近的方法是 friend 声明和前向声明的组合。我该怎么做呢?以下是我的三个文件:

啊哈:

#pragma once
class A
{
    private:
        A();
};

B.h

#pragma once
class A;
class B
{
    public:
        A createA();
};

B.cpp:

#include "A.h"
#include "B.h"

A B::createA()
{
    A result; //cannot access private member declare in class 'A'
    return result;
}

我已尝试将其添加到 A.h:

public: friend A createA();

我尝试将其添加到 A.h 并带有相应的前向声明:

public: friend A B::createA();

我尝试将和 extern class B; 添加到 A.h 并使 B 成为这样的类:

public: friend class B;

我很茫然。

我认为如果我让B::createA() 函数直接返回指向A 对象而不是A 对象的指针,这可能会更容易,但在我的情况下不会这样做。我正在模拟一个封闭的 API,API 调用返回一个 A 对象而不是一个指针。

【问题讨论】:

    标签: c++ friend internal forward-declaration


    【解决方案1】:

    您可能只需要从第三次尝试中删除“extern”即可将其转换为正确的前向声明。试试:

    啊哈:

    #pragma once
    class B;
    class A
    {
        friend class B;
    private:
        A();
    };
    

    【讨论】:

    • 前向声明很可能是他遗漏的。
    • 就是这样。谢谢!是否可以只将createA() 函数设为好友,而不是整个班级?
    • @user2023861:是的。您基本上会复制整个函数签名(包括范围)并将friend 放在它前面。例如:friend A B::CreateA();
    • @ZacHowland 这不起作用,因为B 只是前向声明的。而且你不能在A 之前定义B,因为你已经需要A,因为你是从createA 返回它。
    • 我正想说它没有编译。不要求只有函数是朋友。我会以朋友的身份继续上课。再次感谢!
    【解决方案2】:

    您不需要external 关键字。简单点:

    // In A.h
    
    class B;  // Forward declaration
    
    class A
    {
        friend class B; // Make all the class B friend
        A();
    };
    
    // In B.h
    
    class B
    {
    public:
        A createA() {}
    };
    

    Live Example.

    【讨论】:

      【解决方案3】:

      除非绝对必要,否则您应该让A 自行构造(或拥有创建A 的工厂)。如果你真的想让B 这样做:

      class B; // foward declared
      
      class A
      {
      private:
          A() {}
          friend class B;
      };
      
      class B
      {
      public:
          A CreateA()
          {
              A a;
              return a;
          }
      };
      
      int main()
      {
          B b;
          A a = b.CreateA();
          return 0;
      }
      

      注意:您必须先转发声明B,然后再在A 中声明friend

      如果您只想将功能作为朋友:

      class A;
      
      class B
      {
      public:
          A CreateA();
      };
      
      class A
      {
      private:
          A() {}
          friend class A B::CreateA();
      };
      
      A B::CreateA()
      {
          A a;
          return a;
      }
      
      int main()
      {
          B b;
          A a = b.CreateA();
          return 0;
      }
      

      【讨论】:

      • friend class A B::CreateA(); A 之前添加类键?我的意思是这不是多余的吗?
      • @AngelusMortis 你说BA 的朋友,而不是A 是朋友类。
      【解决方案4】:

      你可以让 B 成为 A 的朋友:

      class A
      {
      private:
         A();
         friend class B;
      };
      

      【讨论】:

        猜你喜欢
        • 2011-02-05
        • 2021-04-17
        • 1970-01-01
        • 2017-09-10
        • 1970-01-01
        • 2011-05-08
        • 2017-04-04
        • 2021-08-27
        • 2013-08-10
        相关资源
        最近更新 更多