【发布时间】:2018-11-22 23:45:23
【问题描述】:
这个问题在某种程度上是a question I have previously asked 的后续问题,因为我正在尝试理解和实施建议的概念。我已将所有内容重构为更小的类,并且武器的整体设计已经完成(并在一定程度上实现了)。但是,我在访问某些成员时遇到了问题,我相信一旦突破了这个障碍,我完成这个项目不会有任何问题,因为很多子类都使用类似的系统。
关于我的问题,我有一个父类,部分是虚拟的,定义如下:
class ModeInformation {
public:
ModeInformation() { m_CreateModes(); m_CreateModeChoiceList(); } // These two functions are always called when an object belonging to the ModeInformation parent class is created, as they store elements in two lists, one in which the pointer-to-Modes themselves are stored, the other where Menu options are stored according to the number of modes
virtual ~ModeInformation() {}
// Modes of a Weapon (virtual as they might be overridden in child classes)
virtual Mode* pMode1() const { return NULL; }
virtual Mode* pMode2() const { return NULL; }
virtual Mode* pMode3() const { return NULL; }
virtual Mode* pMode4() const { return NULL; }
virtual Mode* pMode5() const { return NULL; }
// Lists mentioned earlier
virtual list<string>* ModeChoiceList() const { return new list<string>; }
virtual list<Mode*>* Modes() const { return new list<Mode*>; };
// m_CreateModes() stores pointers-to-Mode in Modes(), if these are not NULL
void m_CreateModes() {
if (!pMode1() == NULL) { Modes()->push_back(pMode1()); }
if (!pMode2() == NULL) { Modes()->push_back(pMode2()); }
if (!pMode3() == NULL) { Modes()->push_back(pMode3()); }
if (!pMode4() == NULL) { Modes()->push_back(pMode4()); }
if (!pMode5() == NULL) { Modes()->push_back(pMode5()); }
}
// m_CreateModeChoiceList() stores strings in ModeChoiceList(), composed using the sstring library. Also a source of problems, as I will point out later on.
void m_CreateModeChoiceList() {
int i = 1;
for (list<Mode*>::iterator it = Modes()->begin(); it != Modes()->end(); it++) {
stringstream ChoiceDeclaration;
ChoiceDeclaration << "\n" << i << ".- Mode " << i;
ModeChoiceList()->push_back(ChoiceDeclaration.str());
i++;
}
ModeChoiceList()->push_back("\n0.- Quit to previous menu.");
}
// m_PrintBasicInfo() is called from classes that possess an object pertaining to the ModeInformation class (or derived child-classes), serves as a decision tree to judge whether the Mode List should be printed (in the case the Weapon being printed possesses more than one Mode), otherwise it will print the very first Mode
void m_PrintBasicInfo() {
if (Modes()->size() > 1) {
m_PrintModeList();
m_ChooseModeFromList();
}
else {
pMode1()->m_PrintBasicInfo(1);
}
}
// m_PrintModeList() prints each of the elements stored in ModeChoiceList()
void m_PrintModeList() {
list<string>::iterator it = ModeChoiceList()->begin();
while (it != ModeChoiceList()->end()) {
cout << *it << endl;
it++;
}
}
// m_ChooseModeFromList() provides a dynamic method for a user to choose which Mode's information will be printed
virtual void m_ChooseModeFromList() {
int Input = 0;
cout << "Please input your choice." << endl;
cin >> Input;
cout << endl;
list<Mode*>::iterator it = Modes()->begin();
switch (Input) {
case 1: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
else { m_ChooseInvalidModeFromList(); break; }
case 2: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
else { m_ChooseInvalidModeFromList(); break; }
case 3: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
else { m_ChooseInvalidModeFromList(); break; }
case 4: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
else { m_ChooseInvalidModeFromList(); break; }
case 5: if (it != Modes()->end()) { (*it)->m_PrintBasicInfo(Input); it++; break; }
else { m_ChooseInvalidModeFromList(); break; }
case 0: cout << "Returning to previous menu..." << endl; break;
default: m_ChooseInvalidModeFromList(); break;
}
}
// m_ChooseInvalidModeFromList() prints an invalid option message, and returns to m_ChooseModeFromList()
void m_ChooseInvalidModeFromList() {
cout << "Invalid option. Please choose a valid mode." << endl;
m_ChooseModeFromList();
}
};
我还有一个属于 Weapon 的示例子类,我用它来测试代码的可行性和执行力。具体如下:
class RailGunModeInformation : public ModeInformation {
public:
Mode* pMode1() const { return new RailGunMode1(); }
Mode* pMode2() const { return new RailGunMode2(); }
list<string>* ModeChoiceList() const { return new list<string>; }
list<Mode*>* Modes() const { return new list<Mode*>; }
};
现在,它可以编译,但我不断收到“Factory Method.exe 中 0x0FC3CAB6 (ucrtbased.dll) 处的未处理异常:将无效参数传递给认为无效参数致命的函数。”错误。无论我在保持其整体功能的同时尝试对其进行多少修改,我似乎都无法使其正常工作,出现大量不同的错误。所以我想我应该向专家寻求帮助,因为我已经花了好几个小时把头撞在墙上试图跳过这个障碍。
【问题讨论】:
-
Wayyyy 在你的代码中有很多星星。你还在学习 C++:不要使用裸指针。尝试使用堆栈对象而不是指向动态分配对象的指针。如果需要,学习和使用参考资料。如果您真的需要指针,请了解智能指针。
-
我假设这里存在大量内存泄漏:您几乎在任何地方都使用
new创建对象,而我看不到一个delete。原始指针应该保留给像容器一样在内部进行资源管理的低级类。所有其他类都应该依赖容器和智能指针。 -
要了解您的错误,有必要查看运行上下文。但是关于代码的一些问题:为什么你使用那个接口:virtual list
* ModeChoiceList() const?对于此函数的每次调用,您都会创建新的空列表,但我看不到您在哪里删除它。这种行为是你想要的吗?你可能需要这样的东西吗?类 A { list modeChoiceList;虚拟列表 & ModeChoiceList() const { return modeChoiceList; } } -
每次调用
Modes(),都会返回一个新的(并且是空的!)列表。所以每次调用it = Modes()->begin(); it != Modes()->end();都会将迭代器与两个不同的列表进行比较。 -
您不需要单独的课程
RailGunModeInformation。 objectModeInformation railgun_modes由Mode railgun_mode_1;和Mode railgun_mode_2;构造而成。ModeInformation需要一个数据成员list<Mode> m_modes(不是返回new list<Mode>的成员函数,它是一个空列表)
标签: c++ list class inheritance