C++ 动态转换失败/子对象被视为父对象
C++ dynamic cast failing / child object gets treated as parent
我想要的只是 java 代码的 C++ 等价物:
如果(ParentClassObject.myIdentifier == "Child1")
(Child1) ParentClassObject ...做事
所以我只想
--把我创建的一个对象作为子对象
-- 在不确定它是什么类型的 Child 的方法中使用它,因此它将它视为 Parent Object
--将其转换为适当的子对象
3 小时后我还没有完成这项工作,我的计算机即将空降。我还阅读了很多关于 OOD 的 SE 文章和教程,但没有 find/didn 不认识解决方案。
在下面的精简代码中,CombatLogLine 是父项,"CombatLogVersionLine" 是子项。 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"));
}
C++ 不是 Java。 C++ 对象从根本上不同于 Java 对象。尝试使用像 Java 对象这样的 C++ 对象肯定会导致失败。
您的 determineTypeOfEvent()
函数 return 是一个超类:
CombatLogLine determineTypeOfEvent(string _aLine)
它正在构造一个子类,然后尝试return它:
CombatLogVersionLine returnValue(_aLine);
// ...
return returnValue;
句号就在这里。不要通过"Go"。不要收取 200 美元。 C++ 不是这样工作的。这就是您在 Java 中做事的方式。但这不是你在 C++ 中做事的方式。在 C++ 中,这个 results in object slicing。该函数不会 return 一个 CombatLogVersion
子类。在通过其复制构造函数构造 CombatLogLine
临时对象后,子类立即被销毁,returning 正是这个函数被声明为 returning: CombatLogLine
。子类被切掉。
在继续您的项目之前,您需要花额外的时间研究 C++ 对象和 类 的工作原理。有几种可能的方法可以正确地做到这一点。通常,在这种情况下,相关函数将 returning a std::shared_ptr<CombatLogLine>
,并在动态范围内构造 return 值;并且此函数的所有调用者都相应地使用 return 值。
这是执行此类操作的一种方法,但不是唯一的方法。在类似情况下可能使用的另一种可能的替代方法是模板,或者可能传递类型擦除的 std::function
回调。很难说,这里正确的方法取决于这个应用程序的细节。
这里的一般答案是:"C++ objects don't work this way, and you should spend more time learning how C++ classes work",以及 C++ 语言的其余部分、它的库和它的所有特性,如模板、智能指针和函数对象,以便为您的问题确定最佳解决方案。在 C++ 中没有即时的满足。
你真的需要完全忘记 Java 对象是如何工作的。如果您尝试使用 C++ 对象,认为它们在某种程度上类似于 Java 对象,这只会让事情变得更加混乱。他们不是。句法、关键字和语法看似相似,但它们完全不同,根本不同。他们以完全不同的方式工作。
我想要的只是 java 代码的 C++ 等价物: 如果(ParentClassObject.myIdentifier == "Child1") (Child1) ParentClassObject ...做事
所以我只想 --把我创建的一个对象作为子对象 -- 在不确定它是什么类型的 Child 的方法中使用它,因此它将它视为 Parent Object --将其转换为适当的子对象
3 小时后我还没有完成这项工作,我的计算机即将空降。我还阅读了很多关于 OOD 的 SE 文章和教程,但没有 find/didn 不认识解决方案。
在下面的精简代码中,CombatLogLine 是父项,"CombatLogVersionLine" 是子项。 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"));
}
C++ 不是 Java。 C++ 对象从根本上不同于 Java 对象。尝试使用像 Java 对象这样的 C++ 对象肯定会导致失败。
您的 determineTypeOfEvent()
函数 return 是一个超类:
CombatLogLine determineTypeOfEvent(string _aLine)
它正在构造一个子类,然后尝试return它:
CombatLogVersionLine returnValue(_aLine);
// ...
return returnValue;
句号就在这里。不要通过"Go"。不要收取 200 美元。 C++ 不是这样工作的。这就是您在 Java 中做事的方式。但这不是你在 C++ 中做事的方式。在 C++ 中,这个 results in object slicing。该函数不会 return 一个 CombatLogVersion
子类。在通过其复制构造函数构造 CombatLogLine
临时对象后,子类立即被销毁,returning 正是这个函数被声明为 returning: CombatLogLine
。子类被切掉。
在继续您的项目之前,您需要花额外的时间研究 C++ 对象和 类 的工作原理。有几种可能的方法可以正确地做到这一点。通常,在这种情况下,相关函数将 returning a std::shared_ptr<CombatLogLine>
,并在动态范围内构造 return 值;并且此函数的所有调用者都相应地使用 return 值。
这是执行此类操作的一种方法,但不是唯一的方法。在类似情况下可能使用的另一种可能的替代方法是模板,或者可能传递类型擦除的 std::function
回调。很难说,这里正确的方法取决于这个应用程序的细节。
这里的一般答案是:"C++ objects don't work this way, and you should spend more time learning how C++ classes work",以及 C++ 语言的其余部分、它的库和它的所有特性,如模板、智能指针和函数对象,以便为您的问题确定最佳解决方案。在 C++ 中没有即时的满足。
你真的需要完全忘记 Java 对象是如何工作的。如果您尝试使用 C++ 对象,认为它们在某种程度上类似于 Java 对象,这只会让事情变得更加混乱。他们不是。句法、关键字和语法看似相似,但它们完全不同,根本不同。他们以完全不同的方式工作。