конструктор шаблонного класса предка с параметром в виде этого же класса
В коде используется неоднократно коллекция std::vector< C_class >, с которой надо делать одни и те же операции. Было принято решение сделать класс - наследник от этой коллекции, который и будет реализовывать необходимые операции.
Вот что вышло.
{
virtual unsigned long __stdcall Func1(...) = 0;
virtual unsigned long __stdcall Func2(...) = 0;
};
template<class T >
class C_VectorWrapper : public vector<T>, public I_FUNCS
{
public:
C_VectorWrapper() : vector<T>() { }
C_VectorWrapper(vector<T>& Vec) : vector<T>(vector<T>& Vec) { }
virtual ~C_VectorWrapper() {}
virtual unsigned long __stdcall Func1(...) { }
virtual unsigned long __stdcall Func2(...) { }
};
Вопрос 1: Как сделать так, чтобы конструктор с параметром передавал параметр в конструктор-предок, чтобы мой класс "наполнялся" вектором, с которым и должен работать?
Кроме того, я не представляю, например, как перегрузить operator=, чтобы в случае, если моему классу приравнивается vector<T>, тот его корректно передавал оператору= своего предка?
Вопрос 2, забавный: как сделать так, чтобы можно было реализацию Func1 и Func2 написать отдельно, а не в объявлении (потому что следующее не помогает:
unsigned long __stdcall C_VectorWrapper<T>::FUNC1(...)
{
//не собирается, и как заставить собираться не понятно.
}
)?
Заранее благодарю.
а это не передача параметра в конструктор предок?
А в твоем вышеприведенном коде оператор = отрабатывает не корректно?
И еще назрел вопрос, смысл "Wrapper" для vector если ты его открыто наследушь?
Вопрос 1: Как сделать так, чтобы конструктор с параметром передавал параметр в конструктор-предок, чтобы мой класс "наполнялся" вектором, с которым и должен работать?
Кроме того, я не представляю, например, как перегрузить operator=, чтобы в случае, если моему классу приравнивается vector<T>, тот его корректно передавал оператору= своего предка?
Что-то я не понял. Вы унаследовались как public от vector<T>... Ну и обращайтесь к своему классу как к vector<T>. Ваш класс в данном случае интерфейсная оболочка, расширяющая функциональность vector<T>. Доделайте методы с наборами необходимых однотипных операций. Зачем нужна в данном случае какая-то дополнительная инициализация в конструкторе не знаю.
Вопрос 2, забавный: как сделать так, чтобы можно было реализацию Func1 и Func2 написать отдельно, а не в объявлении (потому что следующее не помогает:
На сколько я понимаю логику templat'ов такое и не должно работать. Это же шаблонный класс, конкретный класс появится тогда, когда Вы начнете его пользовать (подставите шаблонный тип), соответственно компилятору и методы к этому времени тоже потребуется создать для конкретного класса. Может быть я не прав, но сколько не пытался сам бороться с шаблонами, всегда оказывалось проще записывать все одном h-файле.
На это мой компилятор ругается следующим образом: "improper use of typedef 'vector<C_Class, allocator<C_Class> >' ", причем ругается лишь в том случае, если в коде есть попытка использовать конструктор VectorWrapper(vector<C_Class>& Vec), если я этого нигде не делаю, то не ругается :)
Да, выдает ошибку cannot convert...
Хотелось быстро расширить его функциональные возможности, это кривое архитектурное решение? Если наследовать private, то проще не наследовать, а "хранить" внутри, разве нет?
Да, я так и делаю для всех вызовов уникальных методов класса vector<T>. Но мой класс конфликтует с vector<T> в том случае, если речь идет о конструкторах и операторах, хотелось бы как-то научить его не конфликтовать с ними, вот отсюда и проблема, описанная в первом сообщении.
Да, я так и сделал, реализация методов FUNC1, FUNC2... но хочется "удобной" работы, а у vector<T> есть удобные конструкторы и операторы, которые я потерял и не могу "выудить" назад :)
Но если Вы посмотрите на исходники того же vector<_Tp>, то там прекрасно часть методов реализованы вне template:
void
__vector__<_Tp, _Alloc>::reserve(size_type __n) {
if (capacity() < __n) {
const size_type __old_size = size();
pointer __tmp;
if (this->_M_start) {
__tmp = _M_allocate_and_copy(__n, this->_M_start, this->_M_finish);
_M_clear();
} else {
__tmp = this->_M_end_of_storage.allocate(__n);
}
_M_set(__tmp, __tmp + __old_size, __tmp + __n);
}
}
При этом, когда я использую такой же синтаксис, реализуя методы вне объявления класса, реализация "кушается" компилятором, но при попытке вызвать метод класса, оказывается, что метод не имеет реализации (linker error). Т.е. он с одной стороны видит, что реализация относится к классу и поэтому не ругается на это, с другой стороны он считает, что у класса этот метод все еще не реализован.
Возможно это связано с тем, что мои FUNC1 и FUNC2 принадлежат чужому интерфейсу, который тут лишь наследуется, не являются принадлежащими шаблону "вообще". Но я думаю, что вероятнее всего я что-то использую не так или где-то портачу с синтаксисом :)
Ничего кривого:) Просто для меня wrapper - это немножко другое :) Ну это мои заморочки:)
Со вторым вопросом не согласен, но раздувать флэйм по наследованию реализации не хочу:)
Я немного не понимаю суть проблемы, скинь весь код и как его используешь...
Одну ошибку вижу
Нужно вот так C_VectorWrapper(vector<T>& Vec) : vector<T>(Vec) { }
Вот так работает (MinGW)
{
virtual unsigned long __stdcall Func1() = 0;
virtual unsigned long __stdcall Func2() = 0;
};
template <typename T >
class C_VectorWrapper : public std::vector<T>, public I_FUNCS
{
public:
C_VectorWrapper() : std::vector<T>() { }
C_VectorWrapper(std::vector<T>& Vec) : std::vector<T>(Vec) { }
virtual ~C_VectorWrapper() {}
virtual unsigned long __stdcall Func1() { std::cout << "Func1" << std::endl; return 0; }
virtual unsigned long __stdcall Func2();
};
template <typename T>
unsigned long C_VectorWrapper<T>::Func2()
{
std::cout << "Func2" << std::endl;
return 0;
}
using namespace std;
int main()
{
C_VectorWrapper<int> vInt;
vInt.push_back(10);
vInt.Func1();
vInt.Func2();
return 0;
}
{
void operator ()( const T& value ) const
{
std::cout << value << std::endl;
}
};
void main()
{
std::vector<int> v;
v.push_back( 10 );
v.push_back( 15 );
std::for_each( v.begin(), v.end(), TFunc1<int>() );
}
Вот так работает (MinGW)
unsigned long C_VectorWrapper<T>::Func2()
{
std::cout << "Func2" << std::endl;
return 0;
}
}
Вот эта часть не работает, unresolved external дает компилятор CBuilder 6(( Видимо, дело в нем, хотя он же и ест приведенный выше мною пример реализации vector...
(В таком виде вообще не работает, т.к. при реализации функции забыто __stdcall, но если добавить, то получаю unresolved external).
А с конструктором помогли, спасибо!
Это находится в h-файле?
unsigned long __stdcall C_VectorWrapper<T>::Func2()
{
std::cout << "Func2" << std::endl;
return 0;
}
Это находится в h-файле?
unsigned long __stdcall C_VectorWrapper<T>::Func2()
{
std::cout << "Func2" << std::endl;
return 0;
}
Если в h, то работает, если в cpp, то нет :)
Спасибо, таким образом, понимание механизмов определения шаблонов в этом случае у меня теперь есть.
А кто знает, отчего так, почему тело шаблонной функции должно быть в h файле? Это связано с реализацией шаблонов в си?