Это «распознанный» шаблон ОО? Нужна проверка работоспособности! - PullRequest
2 голосов
/ 24 июля 2010

Скажите, если я хочу расширить функциональность ряда объектов, которые я не могу изменить - например, для добавления форматирования, и не хочу извлекать огромное количество классов для расширения функциональности - будет ли следующее плохо? (Я использую int и float в качестве примера, но в моей программе у меня есть около 20 или 30 классов, которые в конечном итоге окажутся в дереве, которое будет содержать универсальный тип).

class ITreeNode
{
public:
 virtual ~ITreeNode() {}
 virtual void print() = 0;
};

template <class T>
class ObjectNode : public virtual ITreeNode
{
public:
 virtual ~ObjectNode() {}
 ObjectNode(T v)
 {
  m_var = v;
 }
 void print()
 {
  print(m_var);
 }
protected:
 void print(int i)
 {
  printf("int (%d)\r\n", m_var);
 }
 void print(float f)
 {
  printf("float (%f)\r\n", m_var);
 }
 T m_var;
};

int _tmain(int argc, _TCHAR* argv[])
{
 ObjectNode<int> tInt(5);
 ObjectNode<float> tFloat(5.5);
 tInt.print();
 tFloat.print();
 getchar();
 return 0;
}

По сути, мне нужно дерево объектов (одного и того же базового типа), которое я могу вызвать с помощью этих расширенных функций. Первоначально я использовал шаблон посетителя и создавал класс посетителя для каждой расширенной функциональности, в которой я нуждался. Это выглядело очень громоздко и казалось, что вышесказанное будет лучше.

Я думал, что сначала опубликую здесь как проверку работоспособности ..

Заранее спасибо.

Ответы [ 4 ]

1 голос
/ 24 июля 2010

Рассматривали ли вы возможность специализировать свой шаблон для каждого из типов, которые вы хотите напечатать? Это должно работать без изменения способа вызова кода, но также обеспечит некоторую проверку типов во время компиляции, чтобы убедиться, что ваш универсальный тип имеет допустимый метод print ().

template<>
class ObjectNode<int> : public virtual ITreeNode {
    ObjectNode(int v) : m_var(v) {}
    void print() {
        printf("int (%d)\r\n", m_var);
    }
protected:
    int m_var;
};

template<>
class ObjectNode<float> : public virtual ITreeNode {
    ObjectNode(float v) : m_var(v) {}
    void print() {
        printf("float (%f)\r\n", m_var);
    }
protected:
    float m_var;
};
1 голос
/ 25 июля 2010

Это не редкость, нет, но вы можете спросить себя, почему вы вообще используете класс.Почему бы не определить дополнительную функциональность как свободные (не входящие) функции?Затем они работают непосредственно на int и float, без необходимости оборачивать объекты.И ваш код станет намного проще, удобнее в обслуживании и читаемости:

void print(int i)
{
  printf("int (%d)\r\n", m_var);
}
void print(float f)
{
  printf("float (%f)\r\n", m_var);
}

int _tmain(int argc, _TCHAR* argv[])
{
  tInt = 5;
  tFloat = 5.5;
  print(tInt);
  print(tFloat);
 getchar();
 return 0;
}

Нет закона, который гласит, что «ваш код ориентирован только на объект, если все находится внутри класса».Максимально полагаться на функции, не являющиеся членами, можно даже more объектно-ориентированный .

0 голосов
/ 26 июля 2010

Это может работать в вашем простом примере, но не работает полиморфно. То есть, если у вас есть какая-то ссылка на A, но на самом деле это производный тип B, вы все равно создадите ObjectNode<A> и напечатаете его так, как будто это A, а не B. (Хуже того, поскольку ObjectNode принимает значение T, оно будет разрезано. Но это другая история.)

Чтобы полиморфизм работал, вам понадобится шаблон посетителя. Но я вижу в вашем другом вопросе , что вы к этому.

0 голосов
/ 24 июля 2010

Если в итоге у вас будет одна или две реализации print для этих 20-30 классов, да, я бы посчитал, что все в порядке.Но если у вас получится класс ObjectNode с 20-30 реализациями print, я бы сказал, что класс имеет больше зависимостей, чем здоров.

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