有人可以告诉我为什么递归operator=
没有在这里编译?任务很简单。我有一个Menu<T>
类,其中T
是菜单中每个选项的类型。 Menu<WeightedItem<T>>
类只是Menu<T>
的特化,其中WeightedItem<T>
包含项T
以及int
数据成员(出于概率目的)。
我想通过使用其项目并附加一些概率权重(其值与问题无关)将Menu<T>
转换为Menu<WeightedItem<T>>
。问题是菜单可以有子菜单,而子菜单又可以有子菜单,因此我需要递归使用operator=
。到目前为止,这是我的代码:
template <typename T> struct WeightedItem;
template <typename T>
struct Menu
{
struct Option
{
const T item;
Menu* submenu;
Option* next;
Option(const T& t, Menu<T>* menu = nullptr)
: item(t),
submenu(menu),
next(nullptr)
{}
};
Option* first; // first option in the menu
};
template <typename T>
struct WeightedItem {
T item;
int probabilityWeight;
};
template <typename T>
struct Menu<WeightedItem<T>>
{
struct Option
{
const WeightedItem<T> item;
Menu* submenu;
Option* next;
Option(const WeightedItem<T>& t, Menu<WeightedItem<T>>* menu = nullptr)
: item(t),
submenu(menu),
next(nullptr)
{}
Option& operator=(const Option& other)
{
// Needed for defining Menu& operator=(const Menu<T>&).
if (this == & other)
return *this;
item = other.item;
submenu = other.submenu;
next = other.next;
return *this;
}
};
Option* first;
Menu & operator=(const Menu<T>&);
};
template <typename T>
Menu<WeightedItem<T>>& Menu<WeightedItem<T>>::operator=(const Menu<T>& other)
{
delete first;
if (!other.first)
first = nullptr;
else
{
int weight = 1;
Menu<WeightedItem<T>> submenu operator=(*other.first->submenu); // Recursive operator= call for submenus. Won't compile.
first = new Menu<WeightedItem<T>>::Option({other.first->item, weight}, &submenu);
Option* current = first->next;
for (typename Menu<T>::Option* o = other.first->next; o; o = o->next)
{
Menu<WeightedItem<T>> submenu operator=(*o->submenu); // Recursive operator= call for submenus. Won't compile.
current = new Menu<WeightedItem<T>>::Option({o->item, ++weight}, &submenu);
current = current->next;
}
}
return *this;
}
struct Item {};
int main() {
Menu<Item> menu;
Menu<WeightedItem<Item>> weightedMenu;
weightedMenu = menu;
}
但这两个递归调用似乎是非法的。为什么呢?
[Error] expected initializer before 'operator'
如果是非法的,如何解决它?
更新:
好的,所有深度复制都是使用new
进行的多次分配。我不得不简单地放弃operator = idea并简单地定义一个递归函数。我测试过结果也是准确的:
template <typename T> struct WeightedItem;
template <typename T>
struct Menu {
struct Option {
const T item;
Menu* submenu;
Option* next;
Option (const T& t, Menu<T>* menu = nullptr): item(t), submenu(menu), next(nullptr) {}
};
Option* first = nullptr;
};
template <typename T>
struct WeightedItem {
T item;
int probabilityWeight;
};
template <typename T>
struct Menu<WeightedItem<T>> {
struct Option {
const WeightedItem<T> item;
Menu* submenu;
Option* next;
Option (const WeightedItem<T>& t, Menu<WeightedItem<T>>* menu = nullptr): item(t), submenu(menu), next(nullptr) {}
};
Option* first = nullptr;
inline void inheritFrom (const Menu<T>&);
};
template <typename T>
inline void Menu<WeightedItem<T>>::inheritFrom (const Menu<T>& other) {
if (!other.first)
first = nullptr;
else {
int weight = 1;
Menu<WeightedItem<T>>* submenu = nullptr;
if (other.first->submenu) {
submenu = new Menu<WeightedItem<T>>;
submenu->inheritFrom (*other.first->submenu); // Recursive call for submenus.
}
first = new Menu<WeightedItem<T>>::Option ({other.first->item, weight}, submenu);
Option *current = first->next, *prev = first;
for (typename Menu<T>::Option* o = other.first->next; o; o = o->next) {
Menu<WeightedItem<T>>* submenu = nullptr;
if (o->submenu) {
submenu = new Menu<WeightedItem<T>>;
submenu->inheritFrom (*o->submenu); // Recursive call for submenus.
}
current = new Menu<WeightedItem<T>>::Option ({o->item, ++weight}, submenu);
prev->next = current;
if (o->next) {
prev = current;
current = current->next;
}
}
}
}
struct Item {};
int main() {
Menu<Item> menu;
Menu<WeightedItem<Item>> weightedMenu;
weightedMenu.inheritFrom(menu);
}
然而,关于使用=递归的原始问题仍未得到解答。而且似乎c ++不支持它,因为当我尝试使用=来翻译上面的内容时,它不会编译。
答案 0 :(得分:2)
替换
Menu<WeightedItem<T>> submenu operator=(*other.first->submenu);
first = new Menu<WeightedItem<T>>::Option({other.first->item, weight}, &submenu);
通过
first = new Menu<WeightedItem<T>>::Option({other.first->item, weight}, &submenu);
first->submenu->operator=(*other.first->submenu);
或
first = new Menu<WeightedItem<T>>::Option({other.first->item, weight}, &submenu);
*first->submenu = *other.first->submenu;
这是解决问题的起点,但真正的解决方案需要每个选项中的选项和子菜单的深层副本。