2014-10-14 5 views
0

Задача 1: У меня есть следующий код:C++ полиморфизм и VARIADIC Шаблоны

template<typename T, typename S> 
class Base { 
    virtual void fun(const T& arg1, const S& arg2) = 0; 
private: 
    T v1; 
    S v2; 
}; 

class Derived1 : public Base<int, double> { 
public: 
    virtual void fun(int &arg1, double &arg2) override { 
     // do some special stuff 
    } 
}; 

class Derived2 : public Base<float, int> { 
public: 
    virtual void fun(float &arg1, int &arg2) override { 
     // do some special stuff 
    } 
}; 

мне нужно собрать все ссылки на эти объекты (Derived1 & Derived2) в одном векторе к петле над ними и вызывать весело на каждом объекте.

Задача 2: Такая же проблема, но база имеет VARIADIC параметры шаблона Теперь

template<typename T, typename ... S> 
class Base { 
    virtual void fun(const T& arg1) = 0; 
private: 
    T v1; 
    std::tuple<std::vector<S>...> v2; 
}; 

class Derived1 : public Base<int, double, int, int> { 
public: 
    virtual void fun(int &arg1) override { 
     // do some special stuff 
    } 
}; 

class Derived2 : public Base<float, int, double, double> { 
public: 
    virtual void fun(float &arg1) override { 
     // do some special stuff 
    } 
}; 

Есть удобный способ собрать все ссылки на объекты Derived1 и Derived2 в одном векторе?

+0

'станд :: VECTOR' может содержать только элементы одного и того же типа. Следовательно, 'std :: vector' будет неуместным в вашем случае. – 101010

+4

«Мне нужно собрать» - нет, вам это не нужно. Вы можете * думать *, что вам это нужно, но ваша фактическая проблема, о которой вы нам не говорили, скорее всего, имеет совершенно другое и гораздо лучшее решение. –

+0

'abstract' - это не ключевое слово в C++. На каком языке вы пишете? Во-вторых, проблема 1 и проблема 2 почти не связаны, и вы должны задать один вопрос за раз. Это не интерфейс «ask QUESTIONS». И 'std :: tuple >' также не является допустимым. C++, '...' там нельзя использовать. «Эти объекты» также неясны, я понятия не имею, что означает «те». – Yakk

ответ

3

Итак, у вас есть фундаментальное непонимание того, что такое шаблон. Variadic не имеет ничего общего с вашей проблемой.

Рассмотрим следующий шаблон:

template <typename T> 
class Foo 
{ 
T member_; 
public: 
    Foo(){} 
    T& member() {return member_;} 
    virtual bar() {printf("bar");} 
}; 

int main(int argc,char* argv) 
{ 
    Foo<int> a; 
    Foo<string> b; 
} 

Какова взаимосвязь между типами a и b? Ответ - нет. Конечно, они извлекают из одной и той же базы кода, но они являются совершенно разными типами, с разными размерами, интерфейсами и т. Д. И с помощью специализированных шаблонов вы не можете сделать ANY guarentee тем, насколько они похожи.

Что вы пытаетесь сделать, это шаблон вывода полиморфного класса. Так делают именно это:

class Bar 
{ 
public: 
    virtual bar() = 0; 
}; 
template <typename T> 
class Foo : public Bar 
{ 
T member_; 
public: 
    Foo(){} 
    T& member() {return member_;} 
    virtual bar() {printf("bar");} 
}; 

Затем все можно собрать и получить доступ к интерфейсу панели.

Так же, как все наследство, вы можете продолжать предоставлять ребенку классы:

class Derived1 : public Foo<int> { virtual bar() {printf("derived1");}}; 
class Derived2 : public Foo<string> { virtual bar() {printf("derived2");}}; 

Derived1 является Foo<int> является Bar, Derived1 является Foo<string> является Bar.

+0

Да, я это понимаю, но в моем случае класс Base реализует некоторые общие функции для всех подклассов: http://pastebin.com/192Xaef0 Все подклассы теперь создают экземпляр определенного EntitySet с определенным кортежем и ключом. EDIT: я забыл опубликовать виртуальную часть в EntitySet: virtual Tuple select() = 0; – moo

+0

@moo право. В вашем случае вы хотите предоставить интерфейс 'Base' * * только с классом fun(). Тогда у вас может быть * абстрактный класс * templated 'BaseHelper' класс, который наследует от' Base' с вашими фанковыми шаблонами. Тогда вы можете получить конкретный 'Derived1'. Я обновлю свой вопрос, чтобы это отразить. – IdeaHat

+0

Хорошо, это решение, которое не работает для меня. Причина в том, что мои виртуальные функции имеют аргументы и возвращают значения, зависящие от параметров. (см., например, deleteTuple). – moo

1

Добавить еще один не шаблонный базовый класс:

class Intf { 
public: 
    virtual void fun() = 0; 
}; 

template<typename T, typename ... S> 
class Base : public Intf { 
protected: 
    T v1; 
    std::tuple<S...> v2; 
}; 

class Derived1 : public Base<int, double, int, int> { 
public: 
virtual void fun() override { 
    // do some special stuff 
    std::get<0>(v2) = 10; 
    std::get<1>(v2) = 2.5; 
    // ... 
} 
}; 

class Derived2 : public Base<float, int, double, double> { 
public: 
    virtual void fun() override { 
    // do some special stuff 
    float first_elem = std::get<0>(v2); 
    int some_int = std::get<1>(v2); 
    // ... 
    } 
}; 

std::vector<std::shared_ptr<Intf>> vec; 
vec.push_back(std::make_shared<Derived1>()); 
vec.push_back(std::make_shared<Derived2>()); 
+0

Мне нужен вектор, потому что для определенного типа может быть несколько значений экземпляра, и мне нужно их хранить. – moo

+0

@moo: так что в Derived 2 вам нужен вектор с плавающей точкой, вектор ints и 2 вектора удвоений? – Krizz

+0

точно. Но это не мои вопросы. Я спросил, как я могу собрать кучу объектов Derived1 и Derived2 в одном векторе (вне этих классов в самой программе). – moo

 Смежные вопросы

  • Нет связанных вопросов^_^