如何在未定义CListOfTables::CTable时,在CItem类中使用该嵌套类?
解决嵌套类无法前向声明的问题
C++不支持直接前向声明嵌套类(比如class CListOfTables::CTable;这种写法是非法的),针对你遇到的场景,有几种实用的解决方案:
方案一:调整类的声明顺序
利用容器存储指针时仅需要元素类型前向声明的特性,先声明CItem,再定义CListOfTables和嵌套的CTable,最后完成CItem的完整定义。这样CItem声明成员函数时,CTable已经存在。
修改后的代码示例:
#include <string> #include <vector> #include <map> #include <algorithm> #include <set> #include <Windows.h> using namespace std; // 前向声明CItem,CTable是set<CItem*>,仅需指针的前向声明即可 struct CItem; class CListOfTables { public: class CTable : public set<CItem*> { protected: CTable() = delete; CTable(const CTable& druhy) = delete; // 禁用拷贝构造 void operator=(const CTable& kopie) = delete; // 禁用赋值运算符 }; protected: CTable m_sezOfTables[3]; public: CTable& GetTbl(int iType) { return m_sezOfTables[iType]; } }; // 现在可以完整定义CItem,CTable已经存在 struct CItem { protected: wstring m_wsText; protected: CItem(LPCTSTR lsText) : m_wsText(lsText ? lsText : L"") {} CItem() = default; // 默认构造函数 public: LPCTSTR GetText() const { return m_wsText.data(); } void SetText(LPCTSTR lsTxt) { m_wsText = lsTxt; } size_t GetTextSize() const { return m_wsText.size(); } // 此时CTable已定义,可以直接声明函数 inline bool Aktualizuj(CListOfTables::CTable* tbl, CItem* pCopy); }; // 实现成员函数,修正原代码中无返回值的错误 inline bool CItem::Aktualizuj(CListOfTables::CTable* tbl, CItem* pCopy) { if (wcscmp(GetText(), pCopy->GetText()) == 0) return false; auto it = tbl->find(this); if (it != tbl->end()) { CItem* item = *it; tbl->erase(it); item->SetText(pCopy->GetText()); tbl->insert(item); return true; } else return false; } int main() { }
方案二:将嵌套类改为独立类
把CTable从CListOfTables中拆分出来,成为独立的顶层类,这样就可以直接前向声明CTable,解决依赖问题。需要注意通过友元让CListOfTables能访问CTable的私有构造函数。
修改后的代码示例:
#include <string> #include <vector> #include <map> #include <algorithm> #include <set> #include <Windows.h> using namespace std; // 前向声明独立的CTable和CListOfTables class CTable; class CListOfTables; struct CItem { protected: wstring m_wsText; protected: CItem(LPCTSTR lsText) : m_wsText(lsText ? lsText : L"") {} CItem() = default; public: LPCTSTR GetText() const { return m_wsText.data(); } void SetText(LPCTSTR lsTxt) { m_wsText = lsTxt; } size_t GetTextSize() const { return m_wsText.size(); } // 使用前向声明的CTable inline bool Aktualizuj(CTable* tbl, CItem* pCopy); }; // 定义独立的CTable类 class CTable : public set<CItem*> { protected: CTable() = delete; CTable(const CTable& druhy) = delete; void operator=(const CTable& kopie) = delete; // 让CListOfTables可以创建CTable实例 friend class CListOfTables; }; // 定义CListOfTables类 class CListOfTables { protected: CTable m_sezOfTables[3]; public: CTable& GetTbl(int iType) { return m_sezOfTables[iType]; } }; // 实现Aktualizuj函数 inline bool CItem::Aktualizuj(CTable* tbl, CItem* pCopy) { if (wcscmp(GetText(), pCopy->GetText()) == 0) return false; auto it = tbl->find(this); if (it != tbl->end()) { CItem* item = *it; tbl->erase(it); item->SetText(pCopy->GetText()); tbl->insert(item); return true; } else return false; } int main() { }
方案三:转移逻辑到容器类,降低耦合
将更新Item的逻辑从CItem转移到CListOfTables中,让CItem不需要感知容器的存在,遵循迪米特法则,减少类之间的依赖。
修改后的代码示例:
#include <string> #include <vector> #include <map> #include <algorithm> #include <set> #include <Windows.h> using namespace std; struct CItem { protected: wstring m_wsText; protected: CItem(LPCTSTR lsText) : m_wsText(lsText ? lsText : L"") {} CItem() = default; public: LPCTSTR GetText() const { return m_wsText.data(); } void SetText(LPCTSTR lsTxt) { m_wsText = lsTxt; } size_t GetTextSize() const { return m_wsText.size(); } // 移除原Aktualizuj函数,不需要依赖容器类 }; class CListOfTables { public: class CTable : public set<CItem*> { protected: CTable() = delete; CTable(const CTable& druhy) = delete; void operator=(const CTable& kopie) = delete; friend class CListOfTables; }; protected: CTable m_sezOfTables[3]; public: CTable& GetTbl(int iType) { return m_sezOfTables[iType]; } // 将更新逻辑移到容器类中 bool AktualizujItem(CTable* tbl, CItem* item, CItem* pCopy) { if (wcscmp(item->GetText(), pCopy->GetText()) == 0) return false; auto it = tbl->find(item); if (it != tbl->end()) { CItem* foundItem = *it; tbl->erase(it); foundItem->SetText(pCopy->GetText()); tbl->insert(foundItem); return true; } else return false; } }; int main() { }
内容的提问来源于stack exchange,提问作者Michal Hadraba
相关产品推荐
相关产品推荐

