如何在另一个类中访问私有构造函数?

11

我正在用C++编写一个库。我的库中有两个类,AB。我希望隐藏A()构造函数,使得任何引用我的库的代码都无法使用它。但是,我想让B类能够调用A()构造函数。

我来自C#背景,对C++了解不多。在C#中,我可以简单地将A()构造函数声明为internal。我读到说,在C++中最接近这样做的方式是结合friend声明和前向声明。该如何实现呢?以下是我的三个文件:

A.h:

#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();

我尝试在A.h中添加 extern class B;,并将B设置为如下类:

public: friend class B;

我不知所措。

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

4个回答

9
您可能只需要从第三次尝试中删除“extern”,将其转换为正确的前向声明。请尝试:
A.h:
#pragma once
class B;
class A
{
    friend class B;
private:
    A();
};

前向声明很可能是他遗漏的。 - Zac Howland
@user2023861:是的。你基本上需要复制整个函数签名(包括作用域),并在前面加上 friend。例如:friend A B::CreateA(); - Zac Howland
@ZacHowland 这样做不行,因为 B 只有前向声明。而且你不能在 A 之前定义 B,因为你从 createA 返回它时已经需要 A - Daniel Frey
我正要说它编译不了。仅让函数成为友元并不是必需的,我将保持整个类作为友元。再次感谢! - user2023861
@DanielFrey:你需要调换一些东西(并且不能在行内完成),但是可以做到。请看下面我所编辑的内容。 - Zac Howland
显示剩余2条评论

1
除非绝对必要,否则您应该让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;
}

注意: 在声明A中的Bfriend之前,您必须先进行前向声明。

如果您只想将函数声明为友元:

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;
}

为什么你在 A 前面加了 class 关键字呢?我想这不是多余的吗?friend class A B::CreateA(); - Angelus Mortis
@AngelusMortis,您表达的是BA的友元,而不是A是友元类。 - Zac Howland

1

你不需要使用 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() {}
};

实时示例


0

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接