我正在嘗試創建一個將與 4 行 LCD 一起使用的通用選單類。
我有一個特定的(非模板)版本作業,但想擴展它以允許選單修改各種資料型別(int、float、unsigned...)。
這是按預期作業的非模板版本...
/*
* ideally this design allows for defining an arbitrary menu as shown below
* example...
* root1
* sub1-1
* sub1-2
* root 2
* root 3
* sub3-1
* sub3-2
* sub3-2-1
* sub3-2-2
*
* each node in the menu can be executed, and allow for moving to the next/prev sibling or child/parent
* this flexibility requires that each node contains pointers to parent, child, and sibling nodes.
*/
class MenuNode
{
private:
char *prompt;
int value;
public:
MenuNode *parent=NULL;
MenuNode *child=NULL;
MenuNode *prevSibling=NULL;
MenuNode *nextSibling=NULL;
void SetValue(int value)
{
this->value = value;
}
int GetValue()
{
return value;
}
char *Prompt()
{
return prompt;
}
MenuNode(char *prompt, int initialValue, MenuNode *parent, MenuNode *prevSibling)
{
Serial.print(prompt);Serial.println(F(" MenuNode"));
this->prompt = prompt;
if (prevSibling != NULL)
{
this->prevSibling = prevSibling;
prevSibling->SetNextSibling(this);
this->parent = prevSibling->parent;
}
// prevSibling if provided sets the parent
if (prevSibling==NULL && parent != NULL)
{
this->parent = parent;
this->parent->SetChild(this);
}
value = initialValue;
}
void SetChild(MenuNode *child)
{
Serial.print(prompt);Serial.println(F(" SetChild"));
this->child = child;
}
void SetNextSibling(MenuNode *nextSibling)
{
Serial.print(prompt);Serial.println(F(" SetNextSibling"));
this->nextSibling = nextSibling;
}
};
這是一些創建選單結構的測驗代碼......
// Test menu...
MenuNode r1("R1",10,NULL,NULL);
MenuNode r2("R2",20,NULL,&r1);
MenuNode r21("R21",30,&r2,NULL);
MenuNode r22("R22",40,&r2,&r21); // setting parent is optional, the parent will be set by the prev sibling parent
MenuNode r221("R221",50,&r22,NULL);
MenuNode r2211("R2211",60,&r221,NULL);
MenuNode r2212("R2212",70,NULL,&r2211);
MenuNode r3("R3",30,NULL,&r2);
此代碼遍歷列印出結構的每個元素
void PrintMenuStructure(MenuNode *node,int offset)
{
while(node != NULL)
{
for (int i=0;i<offset;i )
Serial.print("-");
Serial.print(node->Prompt());
Serial.print(" = ");
Serial.print(node->Value());
if (node->parent != NULL)
{
Serial.print(" parent=");
Serial.print(node->parent->Prompt());
}
if (node->prevSibling != NULL)
{
Serial.print(" prevSib=");
Serial.print(node->prevSibling->Prompt());
}
if (node->nextSibling != NULL)
{
Serial.print(" nextSib=");
Serial.print(node->nextSibling->Prompt());
}
if (node->child != NULL)
{
Serial.print(" child=");
Serial.print(node->child->Prompt());
}
Serial.println();
if (node->child != NULL)
PrintMenuStructure(node->child, offset);
node = node->nextSibling;
}
}
這是演示選單結構的前一個函式的輸出...
R1 = 10 nextSib=R2
R2 = 20 prevSib=R1 nextSib=R3 child=R21
-R21 = 30 parent=R2 nextSib=R22
-R22 = 40 parent=R2 prevSib=R21 child=R221
--R221 = 50 parent=R22 child=R2211
---R2211 = 60 parent=R221 nextSib=R2212
---R2212 = 70 parent=R221 prevSib=R2211
-R3 = 30 prevSib=R2
這一切都按我想要的方式作業,但 GetValue/SetValue 只對 int 資料進行操作。
我可以創建類的模板版本,GetValue 和 SetValue 的資料型別由模板引數定義,但我現在不知道一旦這樣做就迭代節點。
似乎是一個很簡單的任務,但我已經把頭撞在墻上有一段時間了,還沒有想出任何可行的方法。任何為我指明正確方向的幫助將不勝感激。
我試圖弄清楚如何遍歷類的鏈接串列,但無法弄清楚如何獲取開始迭代的指標。
抱歉,我無法讓代碼格式化作業...... :(
uj5u.com熱心網友回復:
我解釋你的要求的方式:看來你應該讓你的
int value;
一個std::variant。
這是成本最低的路徑。
如果您MenuNode使用其value型別對類進行模板化。那么 aMenuNode<int>*不能是 a 的父級MenuNode<float*>,等等。不是沒有一些努力。您可能最好通過從通用抽象虛擬基礎派生您想要支持的每種型別的值來使其具有多型性,并取決于您希望如何使用value,設計您的界面。
uj5u.com熱心網友回復:
重申一下,我最初對模板版本節點迭代的擔憂是因為不同資料型別的模板版本的物件具有不同的大小。由于我使用 prev/next 指標進行導航,因此大小差異不是問題。如果我想增加/減少指標來導航串列,這只會是一個問題。
當我在考慮如何減小每個選單節點的大小時,我意識到了這一點。由于我實作的聯合方法導致每個節點具有相同的大小,并且由于選單結構永遠不會改變,因此我可以使用 prev/next 的偏移量而不是絕對指標。就在那時燈亮了,我最初的擔心是沒有根據的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/524147.html
標籤:C 模板
