我想要的只是Java代码的C ++: if(ParentClassObject.myIdentifier ==“Child1”) (Child1)ParentClassObject ......做事
所以我想要的就是 - 将我创建的对象作为Child对象 - 在一个不确定它是什么类型的Child的方法中使用它,所以它将它视为父对象 - 将其作为适当的子对象
3个小时后,我无法完成这项工作,我的电脑即将空降。我还阅读了有关OOD的12篇SE文章和教程,但没有找到/不认识解决方案。
在下面的精简代码中,CombatLogLine是Parent,“CombatLogVersionLine”是Child。 determineTypeOfEvent是将其创建为子项的方法,然后将其作为父项返回。完整代码位于https://docs.google.com/document/d/1OXF-YyR0DF0VfdUe9r4OUgPIYNRYXsiMMmQ_fkV-QIQ/edit?usp=sharing
由于某种原因,代码分为两个块,您可能需要向下滚动才能看到第一个块中的所有代码。感兴趣的行中有XXXXXXXXXX。
//CombatLogLine.h
#include stdafx.h
class CombatLogLine
{
public:
bool virtual areFieldsOk();
void virtual parseLine();
string typeOfEvent;
//a bunch of stuff I removed
protected:
string theLineOfRawText;
};
class CombatLogVersionLine : public CombatLogLine
{
public:
CombatLogVersionLine(string _theLineOfRawText) : CombatLogLine(_theLineOfRawText)
{
typeOfEvent = "COMBAT_LOG_VERSION";
}
bool areFieldsOk();
void parseLine();
private:
};
//CombatLogLine.cpp
#include "stdafx.h"
#include "CombatLogLine.h"
CombatLogLine::CombatLogLine(string _theLineOfRawText)
{
//stuff I removed for this example involving _theLineOfRawText
typeOfEvent = "TBA";
}
bool CombatLogLine::areFieldsOk()
{
cout << "This is the base classes areFieldsOk" << endl;
return false;
}
bool CombatLogVersionLine::areFieldsOk()
{
if(typeOfEvent == "COMBAT_LOG_VERSION")
{
if(sizeOfLine == 2)
{
cout << "Hallelujah!" << endl;
return true;
}
}
return false;
}
void CombatLogVersionLine::parseLine()
{
}
// main method
....
for(unsigned int i = 0; i < combatLogSplitIntoLines.size(); i++)
{
CombatLogLine currentLine = determineTypeOfEvent(combatLogSplitIntoLines[i]);//determine type of event also creates an appropriate CombatLogLine
if(currentLine.typeOfEvent == "COMBAT_LOG_VERSION")
{
currentLine.areFieldsOk();
cout << "type id " << typeid(currentLine).name() << endl;
CombatLogVersionLine * temp5 = dynamic_cast<CombatLogVersionLine *>(¤tLine); //XXXXXXXXXXXXXXXXX I don't even want to use pointers here but think I have to
if(temp5 == 0)
{
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX dynamic cast fails
cout << "The dynamic cast failed." << endl;
system("PAUSE");
return 0;
}
temp5->areFieldsOk();
continue;
}
...
//method in main file
CombatLogLine determineTypeOfEvent(string _aLine)
{
if(_aLine == "")
{
cout << "Something went wrong asdghaer" << endl;
system("PAUSE");
}
if(_aLine.find("COMBAT_LOG_VERSION") != string::npos)
{
CombatLogVersionLine returnValue(_aLine);
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXX this works properly and creates a "CombatLogVersionLine"
cout << "A CombatLogVersionLine was created. " << typeid(CombatLogVersionLine).name() << endl;
return returnValue;
}
return (CombatLogLine("FAIL"));
}
答案 0 :(得分:1)
C ++不是Java。 C ++对象与Java对象根本不同。尝试使用像Java对象这样的C ++对象是保证失败的途径。
您的determineTypeOfEvent()
函数返回一个超类:
CombatLogLine determineTypeOfEvent(string _aLine)
它正在构建一个子类,然后尝试返回它:
CombatLogVersionLine returnValue(_aLine);
// ...
return returnValue;
在这里完全停止。不要过去&#34;去&#34;。不要收200美元。 C ++没有这种方式工作。这就是你用Java做事的方式。但这不是你在C ++中做事的方式。在C ++中,这是results in object slicing。该函数不会返回CombatLogVersion
子类。在通过其复制构造函数构造CombatLogLine
临时变量后,子类立即被销毁,并准确返回此函数声明为返回的内容:CombatLogLine
。子类被切掉了。
在继续执行项目之前,您需要花费额外的时间来研究C ++对象和类的工作方式。有几种可能的方法可以正确地执行此操作。通常,在这些情况下,相关函数将返回std::shared_ptr<CombatLogLine>
,并在动态范围内构造返回值;以及此函数的所有调用者都相应地使用返回值。
这是做这样的事情的一种方式,但不是唯一的方法。可能在类似情况下使用的另一种可能的替代方案是模板,或者可能传递类型擦除的std::function
回调。很难说,这里的正确方法取决于此申请的细节。
这里的一般答案是:&#34; C ++对象不能以这种方式工作,你应该花更多的时间来学习C ++类的工作方式,以及C ++的其余部分语言,其库以及模板,智能指针和函数对象等所有功能,以确定解决问题的最佳方案。 C ++中没有即时的满足感。
您确实需要完全忘记Java对象的工作方式。如果你试图使用C ++对象,认为它们在某种程度上类似于Java对象,那只会让事情变得更加混乱。他们不是。语法,关键字和语法看起来看似相似,但它们完全且根本不同。他们以完全不同的方式工作。