如何从内部 class 访问私有构造函数? C++14
How to access private Constructor from within inner class? C++14
我正在尝试将构建器模式应用于一个对象,但是从内部看不到私有构造函数 class。
#include <iostream>
#include <memory>
class Outer{
private:
Outer(void){ std::cout << "Constructed!" << std::endl; }
public:
class Builder{
public:
std::unique_ptr<Outer> build(void){
return std::make_unique<Outer>();
}
};
};
int main(int argc, char** agrs){
std::unique_ptr<Outer> instance = Outer::Builder().build();
return 0;
}
失败并出现以下错误:
In file included from /usr/include/c++/8/memory:80,
from scrap.cpp:2:
/usr/include/c++/8/bits/unique_ptr.h: In instantiation of ‘typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = Outer; _Args = {}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<Outer>]’:
scrap.cpp:11:35: required from here
/usr/include/c++/8/bits/unique_ptr.h:831:30: error: ‘Outer::Outer()’ is private within this context
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
scrap.cpp:6:2: note: declared private here
Outer(void){ std::cout << "Constructed!" << std::endl; }
^~~~~
我在定义中尝试了 friend class Outer::Builder
,但是 Outer
在 friend 子句中不完整,所以我无法使用它。我非常想将对象的实例化限制为 Builder
class,在 C++ 中有什么方法可以做到这一点吗?
还是让 Outer
构造函数 public 成为唯一的选择?
这行不通,因为真正的建造者是std::make_unique
,它既不是朋友也不是会员。让它成为朋友是不可能的,因为你不知道它委托给什么内部函数,而且它无论如何都会破坏私有构造函数的目的。
您可以只使用裸 new
而不是 std::make_unique
,它会在紧要关头工作。如果你想要共享指针而不是唯一指针,这会变得有点问题,因为性能不会那么好。
以下是如何使其适用于 unique_ptr
、shared_ptr
或任何其他类型的句柄。
#include <memory>
class Outer
{
private:
Outer();
public:
class Builder
{
private:
class InnerOuter;
public:
std::unique_ptr<Outer> build();
};
};
class Outer::Builder::InnerOuter : public Outer
{
public:
using Outer::Outer;
};
std::unique_ptr<Outer> Outer::Builder::build()
{
return std::make_unique<InnerOuter>();
}
现在只有 Outer::Builder
可以引用(和构造)一个 InnerOuter
,因为它是私有的 class。但是它的构造函数是public,所以std::make_unique
可以访问它。
注意,InnerOuter
可以访问 Outer
的私有构造函数,因为它是 Outer
成员的成员,并且可以访问 Outer
.
怎么样:
#include <iostream>
#include <memory>
class Outer{
private:
Outer(void){ std::cout << "Constructed!" << std::endl; }
public:
friend class std::unique_ptr<Outer> std::make_unique<Outer>();
class Builder{
public:
std::unique_ptr<Outer> build(void){
return std::make_unique<Outer>();
}
};
};
int main(int argc, char** agrs){
std::unique_ptr<Outer> instance = Outer::Builder().build();
return 0;
}
你也可以在 C++ 中创建友元函数。
根据问题中未描述的细节,还有其他方法可以解决问题。
例如,如果虚拟调用适合您,最简单的方法就是使用工厂模式。这将完全隐藏实现细节(这是使用依赖注入时的常见方法)可以构造对象,因为 Outer
是完全抽象的。
// header
#include <memory>
class Outer {
public:
virtual ~Outer();
virtual void fun1() = 0;
virtual int fun2(int) = 0;
class Builder{
public:
std::unique_ptr<Outer> build(void);
};
#include "Outer.h"
Outer::~Outer() = default;
class ImplOuter : public Outer {
public:
void fun1() override {
// todo
}
int fun2(int) override {
// todo
return 0;
}
};
std::unique_ptr<Outer> Outer::Builder::build(void)
{
return std::make_unique<ImplOuter>();
}
#include <iostream>
#include "Outer.h"
int main(int argc, char** agrs){
auto instance = Outer::Builder().build();
instance->fun1();
return 0;
}
我正在尝试将构建器模式应用于一个对象,但是从内部看不到私有构造函数 class。
#include <iostream>
#include <memory>
class Outer{
private:
Outer(void){ std::cout << "Constructed!" << std::endl; }
public:
class Builder{
public:
std::unique_ptr<Outer> build(void){
return std::make_unique<Outer>();
}
};
};
int main(int argc, char** agrs){
std::unique_ptr<Outer> instance = Outer::Builder().build();
return 0;
}
失败并出现以下错误:
In file included from /usr/include/c++/8/memory:80,
from scrap.cpp:2:
/usr/include/c++/8/bits/unique_ptr.h: In instantiation of ‘typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = Outer; _Args = {}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<Outer>]’:
scrap.cpp:11:35: required from here
/usr/include/c++/8/bits/unique_ptr.h:831:30: error: ‘Outer::Outer()’ is private within this context
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
scrap.cpp:6:2: note: declared private here
Outer(void){ std::cout << "Constructed!" << std::endl; }
^~~~~
我在定义中尝试了 friend class Outer::Builder
,但是 Outer
在 friend 子句中不完整,所以我无法使用它。我非常想将对象的实例化限制为 Builder
class,在 C++ 中有什么方法可以做到这一点吗?
还是让 Outer
构造函数 public 成为唯一的选择?
这行不通,因为真正的建造者是std::make_unique
,它既不是朋友也不是会员。让它成为朋友是不可能的,因为你不知道它委托给什么内部函数,而且它无论如何都会破坏私有构造函数的目的。
您可以只使用裸 new
而不是 std::make_unique
,它会在紧要关头工作。如果你想要共享指针而不是唯一指针,这会变得有点问题,因为性能不会那么好。
以下是如何使其适用于 unique_ptr
、shared_ptr
或任何其他类型的句柄。
#include <memory>
class Outer
{
private:
Outer();
public:
class Builder
{
private:
class InnerOuter;
public:
std::unique_ptr<Outer> build();
};
};
class Outer::Builder::InnerOuter : public Outer
{
public:
using Outer::Outer;
};
std::unique_ptr<Outer> Outer::Builder::build()
{
return std::make_unique<InnerOuter>();
}
现在只有 Outer::Builder
可以引用(和构造)一个 InnerOuter
,因为它是私有的 class。但是它的构造函数是public,所以std::make_unique
可以访问它。
注意,InnerOuter
可以访问 Outer
的私有构造函数,因为它是 Outer
成员的成员,并且可以访问 Outer
.
怎么样:
#include <iostream>
#include <memory>
class Outer{
private:
Outer(void){ std::cout << "Constructed!" << std::endl; }
public:
friend class std::unique_ptr<Outer> std::make_unique<Outer>();
class Builder{
public:
std::unique_ptr<Outer> build(void){
return std::make_unique<Outer>();
}
};
};
int main(int argc, char** agrs){
std::unique_ptr<Outer> instance = Outer::Builder().build();
return 0;
}
你也可以在 C++ 中创建友元函数。
根据问题中未描述的细节,还有其他方法可以解决问题。
例如,如果虚拟调用适合您,最简单的方法就是使用工厂模式。这将完全隐藏实现细节(这是使用依赖注入时的常见方法)可以构造对象,因为 Outer
是完全抽象的。
// header
#include <memory>
class Outer {
public:
virtual ~Outer();
virtual void fun1() = 0;
virtual int fun2(int) = 0;
class Builder{
public:
std::unique_ptr<Outer> build(void);
};
#include "Outer.h"
Outer::~Outer() = default;
class ImplOuter : public Outer {
public:
void fun1() override {
// todo
}
int fun2(int) override {
// todo
return 0;
}
};
std::unique_ptr<Outer> Outer::Builder::build(void)
{
return std::make_unique<ImplOuter>();
}
#include <iostream>
#include "Outer.h"
int main(int argc, char** agrs){
auto instance = Outer::Builder().build();
instance->fun1();
return 0;
}