1

我正在尝试为嵌入式 Linux 系统编写一个在 LCD 上绘制用户界面元素的程序。我有一个名为的基类Widget,它实现了绘图和擦除等基本功能,并具有 x/y 位置和宽度/高度等属性。然后我有派生类Label, Button, 并ProgressBar添加自己的属性(分别为文本、焦点和值)。

我的问题是我想创建一个名为的模板容器类WidgetArray,它将自动生成一个小部件网格,并批量编辑它们的属性。但是,WidgetArray例如,如果包含一个函数,该函数接受一个字符串向量并将每个字符串分配给texta 的属性,如果我声明了一个包含sLabel的实例(它没有文本属性),编译器就会抱怨。这似乎是模板专业化的完美案例。我在cplusplus.com上阅读模板专业化页面时看到了这个:WidgetArrayProgressBar

当我们为一个模板类声明特化时,我们还必须定义它的所有成员,即使是那些与泛型模板类完全相同的成员,因为从泛型模板到特化没有成员“继承”。

请告诉我有办法解决这个问题。的绝大多数成员函数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);
        }
    }
};

我希望我的问题很清楚。我环顾四周,有很多关于模板专业化的帖子,但我没有找到似乎回答我的问题的帖子。

4

1 回答 1

2

听起来您想要的只是一个模板化的基类,其中包含特定于两者的所有方法,然后您可以从中继承。例如:

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
};
于 2013-03-18T00:49:13.937 回答