在模板类中初始化嵌套类的静态实例

时间:2014-09-04 01:27:27

标签: c++ templates static initialization nested

我想这样做:

template <typename T>
class S
{
    ...
    class A
    {
        ~A(){cout << "~A";}
    };
    static A obj;
};

template <typename T>
typename S<T>::A S<T>::obj;

int main()
{...}

但是当程序启动时,不会创建嵌套类A的静态实例。 &#34;〜A&#34;那时候不打印。问题是什么?

2 个答案:

答案 0 :(得分:0)

未使用模板中的静态对象

当您隐式实例化模板类时,只会实例化使用的类的部分。该标准提到了C ++中的静态数据成员.11§14.7.1¶8:

  

类模板的隐式实例化不会导致该类的任何静态数据成员被隐式实例化。

解决方案

您将需要以某种方式引用静态对象的非模板代码,或者您需要显式实例化模板。

请参阅静态对象

由于objS的静态和私有,因此您需要S中引用此对象的一些公共代码。例如,一个返回它的静态方法。

tempalte <typename T>
class S
{
    //... define class A
    static A obj;
public:
    static A & get_obj () { return obj; }
};

template <typename T>
typename S<T>::A S<T>::obj;

然后,您可以从main()调用此方法来隐式实例化obj

int main()
{
    get_obj();
}

显式实例化模板

模板类的显式实例化将完全定义它,就像模板类已被编写为常规类一样。因此,将创建静态对象而无需隐式引用它。

template class S<int>;

关于Singleton模式

隐式实例化行为会减少膨胀

如果您使用的是单身代码,那么您观察到的行为实际上就是您想要的。您只希望在实际使用它们时创建单个对象。这样可以防止未使用的代码占用程序中不必要的资源。

防止膨胀显式实例化

由于希望防止程序的运行时膨胀,因此即使明确地实例化Singleton,也希望这样做。这很自然地通过在返回它的方法中确定单例实例的范围来实现。

template <typename T>
class S
{
    class A
    {
        friend S;
        ~A(){std::cout << "~A\n";}
        static A & getInstance () {
            static A obj;
            return obj;
        }
    };
public:
    void foo () { A::getInstance(); }
};

当静态实例在返回它的静态方法中作用域时,不需要在类之外创建它的模板定义。静态实例仅在调用getInstance()时创建。

答案 1 :(得分:0)

答案取决于问题“...”部分的内容。这是一个使用gcc 4.8.1工作的完整示例;即打印“Ahello~A” 如果你注释掉main()中的代码,那么程序什么都不会产生。

#include <iostream>
using namespace std;
template <typename T>
class S
{
public:
    T m;
    class A
    {
    public:
        A() {cout << "A";}
        void say() {cout << "hello";}
        ~A(){cout << "~A";}
    };
    static A obj;
};

template <typename T>
typename S<T>::A S<T>::obj;

int main() {
    S<int>::obj.say();
}

如果您不在代码中使用static,但仍希望创建静态实例,则jxh给出的答案适用。在这种(不太可能的)情况下,您必须显式实例化模板类: template class S<int>;