我有一个带有私有构造函数和析构函数的模板类:
template <typename T>
class Client
{
private:
Client(...) {}
~Client() {}
template <typename U>
friend class Client<T>& initialize(...);
};
template <typename T>
Client<T> initialize(...)
{
Client<T> client = new Client<T>(...);
}
我不确定朋友的正确语法。有人可以帮忙吗?
答案 0 :(得分:4)
忽略省略号(我假设它是“一堆与问题无关的参数”),这应该有效:
template <typename T>
class Client
{
private:
Client() {} // Note private constructor
public:
~Client() {} // Note public destructor
// Note friend template function syntax
template<typename U>
friend Client<U> initialize();
};
template<typename T>
Client<T> initialize()
{
/* ... */
}
请注意,friend声明与函数声明基本相同,但在返回类型之前以friend
关键字作为前缀。
此外,析构函数是公共的,因此initialize()
的用户将能够销毁返回的Client<>
实例。构造函数仍然是私有的,因此只有initialize()
可以创建它的实例。
上面的代码应该允许这个工作:
int main()
{
Client<int> client = initialize<int>();
}
答案 1 :(得分:1)
template <typename U> friend Client<U> initialize(.....);
答案 2 :(得分:1)
这取决于你想要达到的目的。您可能希望与模板的单个实例化建立联系,或者您可能希望与所有实例进行交互。最后你可能真的不想成为一个模板,而只是一个非模板化的函数,由编译器在你的类模板实例化时自动生成...
与整个模板交朋友:
template <typename T>
class MyClass {
template <typename U>
friend MyClass<U> f();
};
与具体实例进行交流(即允许f<int>
访问MyClass<int>
但不允许访问MyClass<double>
):
// Forward declarations
template <typename T>
class MyClass;
template <typename T>
MyClass<T> f();
// Definition of class template
template <typename T>
class MyClass {
friend MyClass<T> f<T>();
};
// Definition of friend function
template <typename T>
MyClass<T> f() { ... }
自我实例化友好的非模板功能:
template <typename T>
class MyClass {
friend MyClass<T> f() { ... } // define inline
};
我建议您使用后者,除非使用T
MyClass<T>
以外的其他模板参数对函数进行参数化。
答案 3 :(得分:0)
你应该制作你的析构函数public
。如果您需要保留private
,则需要声明另一个friend
函数来删除您创建的Client
个对象。
template <typename T>
class Client
{
private:
Client() {}
~Client() {}
template <typename U>
friend Client<U> *initialize();
template <typename U>
friend void destroy( Client<U> * );
};
template <typename T>
Client<T> *initialize()
{
return new Client<T>();
}
template <typename T>
void destroy( Client<T> *client )
{
delete client;
}
int main()
{
auto client = initialize<int>();
destroy( client );
return 0;
}