C ++, общее программирование и виртуальные функции. Как получить то, что я хочу? - PullRequest
1 голос
/ 26 апреля 2010

Это то, что я хотел бы сделать с помощью шаблонов:

struct op1
{
   virtual void Method1() = 0;
}

...

struct opN
{
   virtual void MethodN() = 0;
}

struct test : op1, op2, op3, op4
{
    virtual void Method1(){/*do work1*/};
    virtual void Method2(){/*do work2*/};
    virtual void Method3(){/*do work3*/};
    virtual void Method4(){/*do work4*/};
}

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

#include <iostream>

template< size_t N >
struct ops : ops< N - 1 >
{
protected:
    virtual void DoStuff(){ std::cout<<N<<std::endl; };
public:
    template< size_t i >
    void Method()
    { if( i < N ) ops<i>::DoStuff(); } 
    //leaving out compile time asserts for brevity
};

template<>
struct ops<0>
{
};

struct test : ops<6>
{
};

int main( int argc, char ** argv )
{
  test obj;
  obj.Method<3>(); //prints 3
  return 0;
}

Однако, как вы, наверное, догадались, я не могу переопределить ни один из 6 методов, которые я унаследовал. Я явно что-то здесь упускаю. В чем моя ошибка? Нет, это не домашняя работа. Это любопытство.

Ответы [ 3 ]

3 голосов
/ 26 апреля 2010

Проверено с GCC 4.3. Даже не знаю, почему я потратил время на это: - /

#include <iostream>

template <std::size_t N>
struct mark
{ };

template <std::size_t N>
struct op : op <N - 1>
{
  virtual  void  do_method (const mark <N>&) = 0;
};

template <>
struct op <1>
{
  virtual  void  do_method (const mark <1>&) = 0;
};

struct test : op <2>
{
  template <std::size_t K>
  void
  method ()
  {  do_method (mark <K> ());  }

  virtual  void do_method (const mark <1>&)
  {  std::cout << "1\n";  }

  virtual  void do_method (const mark <2>&)
  {  std::cout << "2\n";  }
};

int
main ()
{
  test  x;

  x.method <1> ();
  x.method <2> ();
}

Я не знаю, как переместить шаблонную функцию "prettifier" method() из test.

1 голос
/ 26 апреля 2010

Чтобы имитировать ваше первоначальное желание:

#define MAKE_OPS(N) template<> struct Ops<N> : Ops<N-1> { virtual void Method##N() = 0; }

template<int N>
struct Ops;

template<>
struct Ops<0> { };

MAKE_OPS(1);
MAKE_OPS(2);
template<> struct Ops<3> : Ops<2> { virtual void Method3() { std::cout << "3" << std::endl; } };
MAKE_OPS(4);
MAKE_OPS(5);
MAKE_OPS(6);

struct Test : Ops<3> {
    virtual void Method1() { std::cout << 1 << std::endl; }
    virtual void Method2() { std::cout << 2 << std::endl; }
};
1 голос
/ 26 апреля 2010
template< size_t N >
struct ops : ops< N - 1 >

Это кодирует бесконечный цикл. Рекурсия не останавливается, когда N достигает 0. Добавьте специализацию для конечного случая сразу после основного шаблона:

template<>
struct ops<0> {}

Кроме того, что это делает? Почему бы просто не позвонить ops<i>::DoStuff() напрямую?

template< size_t i >
void Method()
{ if( i < N ) ops<i>::DoStuff(); } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...