У меня проблема при попытке инициализировать статические члены шаблона статического класса.

В принципе, я думал, что этот подход будет полезен: у меня есть много объектов, которые, конечно, относятся к одному и тому же базовому типу, но имеют разные типы объектов. Я просто хочу манипулировать этими объектами, поэтому я решил использовать статический шаблон, поскольку существует довольно много разных типов, из которых могут состоять эти объекты.

Однако для ведения журнала и передачи параметров я хотел добавить соответствующие члены в шаблон без необходимости писать инициализаторы для каждого производного статического класса.

Обратите внимание, что следующий код не на самом деле работает, потому что в нем задействован некоторый SDK. Я просто прошу правильного подхода, а не правильного кода.

Заранее спасибо. :)

Template.h:

#ifndef _TEMPLATE_H
#define _TEMPLATE_H

#include "stats.h"

template<class T>
class TemplateObj
{
public:
    static void SetParameters(const Options& options)
    {
        T::_options = options;  // Is this even possible?
        T::Init();
        T::DoStuff(_options);
    }

protected:
    static void Message() { stats.Print("Message from Template static method"); }
    static Stats& TemplateObj<T>::stats = Stats::GetInstance(); // This will not work as this is a non-trivial initializer, how to do it correctly? Stats::GetInstance() retrieves a singleton instance
    static Options& TemplateObj<T>::_options;   // Possible?
};

#endif

Derived.h :

#ifndef _DERIVED_H
#define _DERIVED_H
#include "template.h"

class Derived :TemplateObj < Derived >
{
public:
    static void Init();
    static void DoStuff(Options& options)
};

#endif

Производный.cpp:

#include "derived.h"

void Derived::Init()
{
    // Init stuff here
    TemplateObj::Message(); // Call static method from template directly
}

void Derived::DoStuff(Options& options)
{
    // Do something with options 
    stats.Print("Message from derived static method."); // Access to "stats" here. "stats" should be declared and initialized inside the template.
    options.Load(); // Example
}

Main.h

#include "derived.h"

main()
{
    TemplateObj<Derived>::SetParameters(new Options);
}
0
Robert H. 30 Май 2015 в 21:10
Как и в случае с обычными классами, не являющимися шаблонами, вам необходимо объявить статический член внутри класса, а затем определить его вне класса. Вот так
 – 
Igor Tandetnik
30 Май 2015 в 21:25
@IgorTandetnik: Вот и все! Я новичок в шаблонах, поэтому, возможно, не заметил этого. Большое тебе спасибо! :)
 – 
Robert H.
30 Май 2015 в 23:53

1 ответ

Лучший ответ

По сути, вам не нужно ставить TemplateObj<T>:: перед определением функции, если оно находится внутри определения класса. Следующие два действительны:

template<class T>
class A{
    void func( void );
};

template<class T>
void A<T>::func() { /* Okay */ }

template<class T>
class B {
    void func( void ){ /* Okay */ }
};

В вашем случае замените следующий static Stats& TemplateObj<T>::stats = Stats::GetInstance(); на static Stats& stat() { return Stats::GetInstance(); }

И следующий static Options& TemplateObj<T>::_options; с этим static Options& _options;.

С другой стороны, замените этот T::_options = options; на TemplateObj<T>::_options = options;.

1
Yuchen 30 Май 2015 в 23:36
Спасибо за это. Это не только решает мою первоначальную проблему, но и позволяет передавать другие объекты. :)
 – 
Robert H.
31 Май 2015 в 00:11
К сожалению, поскольку это работает для получения синглтона, для других членов возникает нерешенная внешняя ошибка. Это потому, что я скучаю по внеклассному определению?
 – 
Robert H.
31 Май 2015 в 00:19
@RobertH. Можете ли вы опубликовать, какие ошибки у вас есть прямо сейчас?
 – 
Yuchen
31 Май 2015 в 00:29
Теперь все нормально. Мне просто нужно было добавить определения.
 – 
Robert H.
31 Май 2015 в 00:32
@RobertH. ладно отлично! Рады узнать :)
 – 
Yuchen
31 Май 2015 в 00:33