Интерфейс класса, который может создать N количество методов - PullRequest
0 голосов
/ 08 октября 2018

Я работаю над созданием динамической формы в C ++, которая должна сделать запись пользователя N записей.Число N основано на типе приложения, выбранном пользователем, при условии, что все поля имеют одинаковый тип.Клиент унаследует этот интерфейс.

Поэтому я пытаюсь создать интерфейс (используя шаблоны или любые другие методы), но не могу создать такой интерфейс.

Возможно то же самое -если да, приведите пример?

Пример псевдокода для формы из 10 полей:

template<int i>
class Field {
public:
    Field () {  
    for (int index = 0 ; index < i ; index ++)

    }
};

template<>
class Field<1> {
public:
Field(char * name , int value);
};

class Form : public Field<10>
{
 virtual Field1 (char * name , int value) =0;
 ..........................................
 virtual Field10 (char * name , int value) =0;
 // so based upon the value of N provided this class should have N pure virtual methods
}

Ответы [ 2 ]

0 голосов
/ 09 октября 2018

Не уверен, что понимаю, чего именно вы хотите, но ... я полагаю, вы можете использовать рекурсию и тип тега (скажем, std::integral_constant<std::size_t, N>, где N - аргумент шаблона Field), чтобы различать методы получения и установкина разных уровнях.

Я имею в виду ... учитывая следующее Field

template <typename T, std::size_t N>
class Field : public Field<T, N-1u>
 {
   private:
      std::string  name;
      T            value;

   public:
      using Field<T, N-1u>::setField;
      using Field<T, N-1u>::getFieldName;
      using Field<T, N-1u>::getFieldValue;

      using icnc = std::integral_constant<std::size_t, N> const;

      virtual void setField (icnc &, std::string const & n0, T const & v0)
       {
         name  = n0;
         value = v0;
       }

      virtual std::string const & getFieldName (icnc &) const
       { return name; }

      virtual T const & getFieldValue (icnc &) const
       { return value; }
 };

и наземную специализацию Field<0>, которые определяют поддельные методы

template <typename T>
class Field<T, 0u>
 {
   public:
      // fake ground functions
      virtual void setField      () { };
      virtual void getFieldName  () { };
      virtual void getFieldValue () { };
 };

определяя Form следующим образом

class Form : public Field<int, 10u>
 { };

у вас есть 10 виртуальных сеттеров и 20 (10 для имен и 10 для значений) виртуальных геттеров.

Ниже приведен полный рабочий пример

#include <string>
#include <iostream>
#include <type_traits>

template <typename T, std::size_t N>
class Field : public Field<T, N-1u>
 {
   private:
      std::string  name;
      T            value;

   public:
      using Field<T, N-1u>::setField;
      using Field<T, N-1u>::getFieldName;
      using Field<T, N-1u>::getFieldValue;

      using icnc = std::integral_constant<std::size_t, N> const;

      virtual void setField (icnc &, std::string const & n0, T const & v0)
       {
         name  = n0;
         value = v0;
       }

      virtual std::string const & getFieldName (icnc &) const
       { return name; }

      virtual T const & getFieldValue (icnc &) const
       { return value; }
 };

template <typename T>
class Field<T, 0u>
 {
   public:
      // fake ground functions
      virtual void setField      () { };
      virtual void getFieldName  () { };
      virtual void getFieldValue () { };
 };

class Form : public Field<int, 3u>
 {
   // Form inherit three different setField, three different getFieldName
   // and three different getFieldValie methods
 };

template <std::size_t N>
using tag = std::integral_constant<std::size_t, N> const;


int main ()
 {
   Form  f;

   f.setField(tag<1u>{}, "field 1", 111);
   f.setField(tag<2u>{}, "field 2", 222);
   f.setField(tag<3u>{}, "field 3", 333);

   std::cout << f.getFieldName(tag<1u>{}) << ", "
      << f.getFieldValue(tag<1u>{}) << std::endl;
   std::cout << f.getFieldName(tag<2u>{}) << ", "
      << f.getFieldValue(tag<2u>{}) << std::endl;
   std::cout << f.getFieldName(tag<3u>{}) << ", "
      << f.getFieldValue(tag<3u>{}) << std::endl;
 }

Еще немного поработав внутри Form, добавив установщик шаблонов и пару получателей шаблонов

class Form : public Field<int, 3u>
 {
   public:
      using Field<int, 3u>::setField;
      using Field<int, 3u>::getFieldName;
      using Field<int, 3u>::getFieldValue;

      template <std::size_t N>
      using tag = std::integral_constant<std::size_t, N> const;

      template <std::size_t N>
      void setField (std::string const & n0, int v0)
       { setField(tag<N>{}, n0, v0); }

      template <std::size_t N>
      std::string const & getFieldName () const
       { return getFieldName(tag<N>{}); }

      template <std::size_t N>
      int const & getFieldValue () const
       { return getFieldValue(tag<N>{}); }
 };

, вы можете упростить использование индекса тега

   Form  f;

   f.setField<1u>("field 1", 111);
   f.setField<2u>("field 2", 222);
   f.setField<3u>("field 3", 333);

   std::cout << f.getFieldName<1u>() << ", " << f.getFieldValue<1u>()
      << std::endl;
   std::cout << f.getFieldName<2u>() << ", " << f.getFieldValue<2u>()
      << std::endl;
   std::cout << f.getFieldName<3u>() << ", " << f.getFieldValue<3u>()
      << std::endl;
0 голосов
/ 08 октября 2018

Есть много разных способов сделать это.

Вы сказали, что хотите, чтобы все поля одного типа.

Вот простое решение с вектором.

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

/*********************
 *  File: main.cpp   *
 *********************/

#include <iostream>
#include "Form.h"

using std::cout;
using std::endl;

int main(int argc, char* argv[])
{
    Form<int> form(15);

    // The first field is the customer number
    form.setFieldName(0, "customer number");
    form.setFieldValue(0, 4711);

    // The second field is the order number
    form.setFieldName(1, "order number");
    form.setFieldValue(1, 1234);

    // The third field is an article number
    form.setFieldName(2, "article number");
    form.setFieldValue(2, 6789);

    // ... and so on ...
    // Read some values back

    cout << "This is the second field:" << endl;
    cout << "Field Name:  [" << form.getFieldName(1) << "]" << endl;
    cout << "Field Value: [" << form.getFieldValue(1) << "]" << endl;

    return 0;
}

А вот шаблон, включенный в Main.cpp:

/*****************
 * File: Form.h  *
 *****************/

#pragma once
#include "FormField.h"

template<class T>
class Form
{
public:
    explicit Form(const int size);
    virtual ~Form() = default;
    void setFieldName(int index, const std::string& name);
    const std::string& getFieldName(int index) const;
    void setFieldValue(int index, const T& value);
    const T& getFieldValue(int index) const;
private:
    std::vector<FormField<T>> formFields;
};

template<class T>
Form<T>::Form(const int size)
    : formFields(size)
{ }

template<class T>
void Form<T>::setFieldName(int index, const std::string& name)
{
    formFields[index].setName(name);
}

template<class T>
const std::string& Form<T>::getFieldName(int index) const
{
    return formFields[index].getName();
}

template<class T>
void Form<T>::setFieldValue(int index, const T& value)
{
    formFields[index].setValue(value);
}

template<class T>
const T& Form<T>::getFieldValue(int index) const
{
    return formFields[index].getValue();
}

И вот шаблон для FormField:

/**********************
 * File: FormField.h  *
 **********************/

#pragma once
#include <string>
#include <vector>

template<class T>
class FormField
{
public:
    explicit FormField();
    virtual ~FormField() = default;
    const std::string& getName() const;
    void setName(const std::string& name);
    const T& getValue() const;
    void setValue(const T& value);
private:
    std::string name;
    T value;
};

template<class T>
FormField<T>::FormField()
    : name(), value()
{
}

template<class T>
const std::string& FormField<T>::getName() const
{
    return name;
}

template<class T>
const T& FormField<T>::getValue() const
{
    return value;
}

template<class T>
void FormField<T>::setName(const std::string& name)
{
    this->name = name;
}

template<class T>
void FormField<T>::setValue(const T& value)
{
    this->value = value;
}

Вот и все.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...