友元函数无法构造类的唯一指针

Friend function is unable to construct a unique pointer of the class

本文关键字:唯一 指针 函数 友元      更新时间:2023-10-16

我有一定的设计策略,其中我的类的构造函数是私有的,只能由类的朋友构造。 在 friend 函数中,我尝试使用 std::make_unique 创建我的类的unique_pointer,但它无法编译。我的 VC12 编译器抱怨

C:\Program Files (x86)\Microsoft Visual Studio 12.0\vc\include\memory(1639):错误 C2248:"垃圾邮件::垃圾邮件":无法访问在类"垃圾邮件"中声明的私有成员

编译过程中失败的相关代码如下

#include <memory>
class Spam {
public:
    friend void Foo();
private:
    Spam(int mem) :mem(mem) {}
    int mem;
};
void Foo() {
    std::unique_ptr<Spam> spam = std::make_unique<Spam>(10);
}

为什么我无法编译?

这是我看到的另一种方法,显然称为密钥习惯用法:让公共构造函数需要私有访问令牌。

class Spam {
    struct Token {};
    friend void Foo();
public:
    Spam(Token, int mem) : mem(mem) {}
private:
    int mem;
};
void Foo() {
    std::unique_ptr<Spam> spam = std::make_unique<Spam>(Spam::Token{}, 10);
}
void Bar() {
    // error: 'Spam::Token Spam::token' is private
    // std::unique_ptr<Spam> spam = std::make_unique<Spam>(Spam::Token{}, 10);
}

在您的情况下,函数make_unique正在尝试创建Spam的实例,而该函数不是友元。从友元函数内部调用非友元函数不会使非友元函数充满友元状态。

要解决这个问题,你可以用Foo写:

std::unique_ptr<Spam> spam(new Spam(10));
Why am I not able to compile?

您无法编译,因为make_unique不是Spam的朋友。

make_unique成为朋友的另一种解决方案是将unique_ptr的创建移至 Spam .

class Spam {
   ...
private:
   Spam(int) {}
   static unique_ptr<Spam> create( int i ) 
   { return std::unique_ptr<Spam>( new Spam(i) ); }
};

然后Foo叫它。

void Foo() {
    std::unique_ptr<Spam> spam = Spam::create(10);
    ...
}

在您的示例中,Foo() 是一个 friend ,但创建Spam的不是函数 - make_unique在内部调用new Spam本身。简单的解决方法是直接Foo()实际构造Spam

void Foo() {
    std::unique_ptr<Spam> spam(new Spam(10));
}