Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

конструктор шаблонного класса предка с параметром в виде этого же класса

1.8K
03 марта 2011 года
Arkady
153 / / 18.12.2007
Здравствуйте,

В коде используется неоднократно коллекция std::vector< C_class >, с которой надо делать одни и те же операции. Было принято решение сделать класс - наследник от этой коллекции, который и будет реализовывать необходимые операции.
Вот что вышло.
Код:
struct I_FUNCS
{
    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 написать отдельно, а не в объявлении (потому что следующее не помогает:
 
Код:
template< class T >
unsigned long __stdcall C_VectorWrapper<T>::FUNC1(...)
{
//не собирается, и как заставить собираться не понятно.
}

)?

Заранее благодарю.
38K
03 марта 2011 года
alt@zir
29 / / 28.08.2008
Цитата:
C_VectorWrapper(vector<T>& Vec) : vector<T>(vector<T>& Vec) { }

а это не передача параметра в конструктор предок?
А в твоем вышеприведенном коде оператор = отрабатывает не корректно?
И еще назрел вопрос, смысл "Wrapper" для vector если ты его открыто наследушь?

412
03 марта 2011 года
grgdvo
323 / / 04.07.2007
Цитата: Arkady

Вопрос 1: Как сделать так, чтобы конструктор с параметром передавал параметр в конструктор-предок, чтобы мой класс "наполнялся" вектором, с которым и должен работать?
Кроме того, я не представляю, например, как перегрузить operator=, чтобы в случае, если моему классу приравнивается vector<T>, тот его корректно передавал оператору= своего предка?


Что-то я не понял. Вы унаследовались как public от vector<T>... Ну и обращайтесь к своему классу как к vector<T>. Ваш класс в данном случае интерфейсная оболочка, расширяющая функциональность vector<T>. Доделайте методы с наборами необходимых однотипных операций. Зачем нужна в данном случае какая-то дополнительная инициализация в конструкторе не знаю.

Цитата: Arkady

Вопрос 2, забавный: как сделать так, чтобы можно было реализацию Func1 и Func2 написать отдельно, а не в объявлении (потому что следующее не помогает:


На сколько я понимаю логику templat'ов такое и не должно работать. Это же шаблонный класс, конкретный класс появится тогда, когда Вы начнете его пользовать (подставите шаблонный тип), соответственно компилятору и методы к этому времени тоже потребуется создать для конкретного класса. Может быть я не прав, но сколько не пытался сам бороться с шаблонами, всегда оказывалось проще записывать все одном h-файле.

1.8K
03 марта 2011 года
Arkady
153 / / 18.12.2007
Цитата: alt@zir
а это не передача параметра в конструктор предок?



На это мой компилятор ругается следующим образом: "improper use of typedef 'vector<C_Class, allocator<C_Class> >' ", причем ругается лишь в том случае, если в коде есть попытка использовать конструктор VectorWrapper(vector<C_Class>& Vec), если я этого нигде не делаю, то не ругается :)

Цитата: alt@zir
А в твоем вышеприведенном коде оператор = отрабатывает не корректно?


Да, выдает ошибку cannot convert...

Цитата: alt@zir
И еще назрел вопрос, смысл "Wrapper" для vector если ты его открыто наследушь?


Хотелось быстро расширить его функциональные возможности, это кривое архитектурное решение? Если наследовать private, то проще не наследовать, а "хранить" внутри, разве нет?

1.8K
03 марта 2011 года
Arkady
153 / / 18.12.2007
Цитата: grgdvo
Что-то я не понял. Вы унаследовались как public от vector<T>... Ну и обращайтесь к своему классу как к vector<T>. Ваш класс в данном случае интерфейсная оболочка, расширяющая функциональность vector<T>.


Да, я так и делаю для всех вызовов уникальных методов класса vector<T>. Но мой класс конфликтует с vector<T> в том случае, если речь идет о конструкторах и операторах, хотелось бы как-то научить его не конфликтовать с ними, вот отсюда и проблема, описанная в первом сообщении.

Цитата: grgdvo
Доделайте методы с наборами необходимых однотипных операций. Зачем нужна в данном случае какая-то дополнительная инициализация в конструкторе не знаю.


Да, я так и сделал, реализация методов FUNC1, FUNC2... но хочется "удобной" работы, а у vector<T> есть удобные конструкторы и операторы, которые я потерял и не могу "выудить" назад :)

Цитата: grgdvo
На сколько я понимаю логику templat'ов такое и не должно работать. Это же шаблонный класс, конкретный класс появится тогда, когда Вы начнете его пользовать (подставите шаблонный тип), соответственно компилятору и методы к этому времени тоже потребуется создать для конкретного класса. Может быть я не прав, но сколько не пытался сам бороться с шаблонами, всегда оказывалось проще записывать все одном h-файле.


Но если Вы посмотрите на исходники того же vector<_Tp>, то там прекрасно часть методов реализованы вне template:

Код:
template <class _Tp, class _Alloc>
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 принадлежат чужому интерфейсу, который тут лишь наследуется, не являются принадлежащими шаблону "вообще". Но я думаю, что вероятнее всего я что-то использую не так или где-то портачу с синтаксисом :)
38K
04 марта 2011 года
alt@zir
29 / / 28.08.2008
Цитата:
Хотелось быстро расширить его функциональные возможности, это кривое архитектурное решение? Если наследовать private, то проще не наследовать, а "хранить" внутри, разве нет?


Ничего кривого:) Просто для меня wrapper - это немножко другое :) Ну это мои заморочки:)
Со вторым вопросом не согласен, но раздувать флэйм по наследованию реализации не хочу:)
Я немного не понимаю суть проблемы, скинь весь код и как его используешь...

Одну ошибку вижу

Цитата:
C_VectorWrapper(vector<T>& Vec) : vector<T>(vector<T>& Vec) { }


Нужно вот так C_VectorWrapper(vector<T>& Vec) : vector<T>(Vec) { }

535
04 марта 2011 года
Нездешний
537 / / 17.01.2008
Выделенное красным - не надо.
Цитата:
C_VectorWrapper(vector<T>& Vec) : vector<T>([COLOR="#ff0000"]vector<T>& [/COLOR]Vec) { }


Вот так работает (MinGW)

Код:
struct I_FUNCS
{
    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;
}
38K
04 марта 2011 года
alt@zir
29 / / 28.08.2008
Исправишь копирующий конструктор, и оператор = будет работать.
13K
06 марта 2011 года
MihaZzz
18 / / 06.03.2006
А не проще написать классы-функции?
Код:
template<class T> struct TFunc1
{
    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>() );
}
1.8K
08 марта 2011 года
Arkady
153 / / 18.12.2007
Цитата: Нездешний
Выделенное красным - не надо.
Вот так работает (MinGW)
 
Код:
template <typename T>
unsigned long C_VectorWrapper<T>::Func2()
{
    std::cout << "Func2" << std::endl;
    return 0;
}
}


Вот эта часть не работает, unresolved external дает компилятор CBuilder 6(( Видимо, дело в нем, хотя он же и ест приведенный выше мною пример реализации vector...
(В таком виде вообще не работает, т.к. при реализации функции забыто __stdcall, но если добавить, то получаю unresolved external).

А с конструктором помогли, спасибо!

535
08 марта 2011 года
Нездешний
537 / / 17.01.2008
__stdcall потерял, да :)

Это находится в h-файле?
 
Код:
template <typename T>
unsigned long __stdcall C_VectorWrapper<T>::Func2()
{
    std::cout << "Func2" << std::endl;
    return 0;
}
1.8K
10 марта 2011 года
Arkady
153 / / 18.12.2007
Цитата: Нездешний
__stdcall потерял, да :)

Это находится в h-файле?
 
Код:
template <typename T>
unsigned long __stdcall C_VectorWrapper<T>::Func2()
{
    std::cout << "Func2" << std::endl;
    return 0;
}


Если в h, то работает, если в cpp, то нет :)
Спасибо, таким образом, понимание механизмов определения шаблонов в этом случае у меня теперь есть.

А кто знает, отчего так, почему тело шаблонной функции должно быть в h файле? Это связано с реализацией шаблонов в си?

38K
11 марта 2011 года
alt@zir
29 / / 28.08.2008
Для разворачивания шаблона должен быть прямой просмотр препроцессором от точки вызова до шаблона(не декларации!!). Вариант, что функция соберется в отдельном объектном файле, а потом подключится компоновщиком не канает. В принципе можешь подключить инклюдом *.cpp файл в котором находится шаблон, тоже будет работать, но это некрасиво.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог