Я пытаюсь написать программу, которая рисует элементы пользовательского интерфейса на ЖК-дисплее для встроенной системы Linux. У меня есть базовый класс под названием Widget
, который реализует базовые функции, такие как рисование и стирание, и имеет такие атрибуты, как положение x / y и ширина / высота. Затем я создал производные классы Label
, Button
и ProgressBar
, которые добавляют свои собственные атрибуты (текст, фокус и значение соответственно).
Моя проблема в том, что я хочу создать класс контейнера шаблона под названием WidgetArray
, который будет автоматически генерировать сетку виджетов и массово редактировать их свойства. Однако, если WidgetArray
содержит, например, функцию, которая принимает вектор строк и назначает каждую строку свойству text
объекта Label
, если я объявляю экземпляр WidgetArray
, содержащие ProgressBar
(у которых нет текстового атрибута), компилятор жалуется. Кажется, это идеальный случай для специализации шаблонов. Я читал страницу о специализации шаблонов на cplusplus.com и увидел следующее:
Когда мы объявляем специализации для шаблонного класса, мы также должны определить все его члены, даже те, которые точно равны универсальному шаблонному классу, потому что нет «наследования» членов от универсального шаблона к специализации.
Пожалуйста, скажите мне, что есть способ обойти это. Подавляющее большинство функций-членов WidgetArray
совершенно справедливо для всех производных классов Widget
, и кажется невероятно глупым, что мне приходится копировать и вставлять весь код для WidgetArray
просто для добавления одной специализированной функции для производного класса.
Вот несколько упрощенная версия кода, который у меня есть:
template<class T>
class WidgetArray {
protected:
std::vector<T> children;
int columns, x, y;
int element_w, element_h;
int x_padding, y_padding;
public:
WidgetArray() {
columns = 1;
children.resize(1);
x = 0;
y = 0;
}
WidgetArray(int x_in, int y_in, int size, int cols) {
unsigned int counter1=0, counter2=0;
columns = cols;
x = x_in;
y = y_in;
element_w = 10;
element_h = 10;
x_padding = 0;
y_padding = 0;
children.resize(size);
for (unsigned ii = 0; ii < size; ii++) {
if (counter1 > columns) {
counter1 = 0; //column number
counter2++; //row number
}
children.at(ii).x = counter1*(element_w + x_padding) + x;
children.at(ii).y = counter2*(element_h + y_padding) + y;
children.at(ii).width = element_w;
children.at(ii).height = element_h;
}
}
void draw_children(std::vector<unsigned char>& cmd_str){
for (unsigned ii=0; ii < children.size(); ii++) children.at(ii).draw(cmd_str);
}
void redraw_children(std::vector<unsigned char>& cmd_str) {
for (unsigned ii=0; ii < children.size(); ii++) {
children.at(ii).erase(cmd_str);
children.at(ii).draw(cmd_str);
}
}
void erase_children(std::vector<unsigned char>& cmd_str) {
for (unsigned ii=0; ii < children.size(); ii++) children.at(ii).erase(cmd_str);
}
int reform(int num_elements, int cols, int x_in, int y_in) {
unsigned int counter1=0, counter2=0;
children.clear();
children.resize(num_elements);
columns = cols;
x = x_in;
y = y_in;
for (unsigned ii = 0; ii < children.size(); ii++) {
if (counter1 > columns) {
counter1 = 0; //column number
counter2++; //row number
}
children.at(ii).x = counter1*(element_w + x_padding) + x;
children.at(ii).y = counter2*(element_h + y_padding) + y;
children.at(ii).width = element_w;
children.at(ii).height = element_h;
}
return 1;
}
int assign_text(std::vector<string> text) {
for (unsigned ii=0; ii<children.size() || ii < text.size(); ii++) {
//This is only valid if my type is a Button or Label but I want
//the rest of the code for WidgetArray to be valid for any derived
//class of Widget
children.at(ii).text = text.at(ii);
}
}
};
Надеюсь, мой вопрос ясен. Я огляделся и нашел много сообщений о специализации шаблонов, но не нашел ни одного, которое, казалось бы, отвечало на мой вопрос.
1 ответ
Похоже, что вам нужен просто шаблонный базовый класс, содержащий все методы, специфичные для обоих, от которых вы затем наследуете. Например:
template <typename T>
struct base
{
protected:
std::vector<T> children;
~base() { }
public:
void draw_children();
//Other methods common to all template parameters T
};
class WidgetArrayString
: public base<std::string>
{
//Methods specific only to strings
};
class WidgetArrayProgressBar
: public base<ProgressBar>
{
//Methods specific only to progress bar
};
Похожие вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.
class ProgressBarArray : public WidgetArray<ProgressBar>
, и добавить методы для индикаторов выполнения в тот класс; не по специализации? Или я совершенно неправильно понял вопрос и конечную цель? Другими словами, я не уверен, почему вы думаете, что специализация - правильный ответ?