mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-20 03:23:23 +08:00
[0.1.x] fixed : issue #10767 ( typeInfo raises symbolException for classes with diamond virtual inheritance )
git-svn-id: https://pykd.svn.codeplex.com/svn@76514 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
2527901eed
commit
d1a30dc6b0
@ -178,6 +178,23 @@ int Symbol::getVirtualBasePointerOffset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG Symbol::getVirtualBaseDispIndex()
|
||||||
|
{
|
||||||
|
return callSymbol(get_virtualBaseDispIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG Symbol::getVirtualBaseDispSize()
|
||||||
|
{
|
||||||
|
SymbolPtr baseTableType = SymbolPtr( new Symbol( callSymbol(get_virtualBaseTableType), m_machineType ) );
|
||||||
|
|
||||||
|
return (ULONG)baseTableType->getType()->getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void Symbol::getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue)
|
void Symbol::getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue)
|
||||||
{
|
{
|
||||||
HRESULT hres = _symbol->get_value(&vtValue);
|
HRESULT hres = _symbol->get_value(&vtValue);
|
||||||
|
@ -162,6 +162,10 @@ public:
|
|||||||
|
|
||||||
int getVirtualBasePointerOffset();
|
int getVirtualBasePointerOffset();
|
||||||
|
|
||||||
|
ULONG getVirtualBaseDispIndex();
|
||||||
|
|
||||||
|
ULONG getVirtualBaseDispSize();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::pair<ULONG, const char *> ValueNameEntry;
|
typedef std::pair<ULONG, const char *> ValueNameEntry;
|
||||||
|
|
||||||
|
@ -238,7 +238,34 @@ UdtTypedVar::getField( const std::string &fieldName )
|
|||||||
return TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) );
|
return TypedVar::getTypedVar( m_client, fieldType, VarDataMemory::factory(m_dataSpaces, fieldType->getStaticOffset() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldType->getOffset()) );
|
ULONG fieldOffset = 0;
|
||||||
|
|
||||||
|
fieldOffset = fieldType->getOffset();
|
||||||
|
|
||||||
|
if ( fieldType->isVirtualMember() )
|
||||||
|
{
|
||||||
|
fieldOffset += getVirtualBaseDisplacement( fieldType );
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LONG UdtTypedVar::getVirtualBaseDisplacement( TypeInfoPtr& typeInfo )
|
||||||
|
{
|
||||||
|
ULONG virtualBasePtr, virtualDispIndex, virtualDispSize;
|
||||||
|
typeInfo->getVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize );
|
||||||
|
|
||||||
|
ULONG64 vbtableOffset = m_varData->fork( virtualBasePtr )->readPtr();
|
||||||
|
|
||||||
|
VarDataPtr vbtable = VarDataMemory::factory(m_dataSpaces, vbtableOffset);
|
||||||
|
|
||||||
|
LONG displacement = 0;
|
||||||
|
|
||||||
|
vbtable->read( &displacement, sizeof(displacement), virtualDispIndex*virtualDispSize );
|
||||||
|
|
||||||
|
return virtualBasePtr + displacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -264,8 +291,15 @@ std::string UdtTypedVar::print()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fieldVar = TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldType->getOffset()) );
|
ULONG fieldOffset = fieldType->getOffset();
|
||||||
sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset();
|
|
||||||
|
if ( fieldType->isVirtualMember() )
|
||||||
|
{
|
||||||
|
fieldOffset += getVirtualBaseDisplacement( fieldType );
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldVar = TypedVar::getTypedVar( m_client, fieldType, m_varData->fork(fieldOffset) );
|
||||||
|
sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldOffset;
|
||||||
sstr << " " << std::left << std::setw(24) << std::setfill(' ') << m_typeInfo->getFieldNameByIndex(i) << ':';
|
sstr << " " << std::left << std::setw(24) << std::setfill(' ') << m_typeInfo->getFieldNameByIndex(i) << ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +177,8 @@ public:
|
|||||||
virtual std::string printValue();
|
virtual std::string printValue();
|
||||||
|
|
||||||
virtual TypedVarPtr getField( const std::string &fieldName );
|
virtual TypedVarPtr getField( const std::string &fieldName );
|
||||||
|
|
||||||
|
LONG getVirtualBaseDisplacement( TypeInfoPtr& typeInfo );
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -475,10 +475,39 @@ TypeInfoPtr TypeInfo::getRecurciveComplexType( TypeInfoPtr &lowestType, std::str
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG64 TypeInfo::getStaticOffset() {
|
||||||
|
if ( !m_staticMember )
|
||||||
|
throw TypeException( getName(), "This is not a static member" );
|
||||||
|
|
||||||
|
return m_staticOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG TypeInfo::getOffset() {
|
||||||
|
|
||||||
|
if ( m_staticOffset )
|
||||||
|
throw TypeException( getName(), "This is a static member" );
|
||||||
|
|
||||||
|
return m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG64 TypeInfo::getTypeOffset()
|
||||||
|
{
|
||||||
|
return m_staticMember ? m_staticOffset : m_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TypeInfoPtr UdtTypeInfo::getField( const std::string &fieldName )
|
TypeInfoPtr UdtTypeInfo::getField( const std::string &fieldName )
|
||||||
{
|
{
|
||||||
if ( m_fields.empty() )
|
if ( m_fields.empty() )
|
||||||
getFields( m_dia );
|
{
|
||||||
|
getFields( m_dia, pyDia::SymbolPtr() );
|
||||||
|
getVirtualFields();
|
||||||
|
}
|
||||||
|
|
||||||
FieldList::reverse_iterator it;
|
FieldList::reverse_iterator it;
|
||||||
|
|
||||||
@ -495,7 +524,10 @@ TypeInfoPtr UdtTypeInfo::getField( const std::string &fieldName )
|
|||||||
TypeInfoPtr UdtTypeInfo::getFieldByIndex( ULONG index )
|
TypeInfoPtr UdtTypeInfo::getFieldByIndex( ULONG index )
|
||||||
{
|
{
|
||||||
if ( m_fields.empty() )
|
if ( m_fields.empty() )
|
||||||
getFields( m_dia );
|
{
|
||||||
|
getFields( m_dia, pyDia::SymbolPtr() );
|
||||||
|
getVirtualFields();
|
||||||
|
}
|
||||||
|
|
||||||
return m_fields[ index ].second;
|
return m_fields[ index ].second;
|
||||||
}
|
}
|
||||||
@ -505,7 +537,10 @@ TypeInfoPtr UdtTypeInfo::getFieldByIndex( ULONG index )
|
|||||||
std::string UdtTypeInfo::getFieldNameByIndex( ULONG index )
|
std::string UdtTypeInfo::getFieldNameByIndex( ULONG index )
|
||||||
{
|
{
|
||||||
if ( m_fields.empty() )
|
if ( m_fields.empty() )
|
||||||
getFields( m_dia);
|
{
|
||||||
|
getFields( m_dia, pyDia::SymbolPtr() );
|
||||||
|
getVirtualFields();
|
||||||
|
}
|
||||||
|
|
||||||
return m_fields[ index ].first;
|
return m_fields[ index ].first;
|
||||||
}
|
}
|
||||||
@ -515,14 +550,23 @@ std::string UdtTypeInfo::getFieldNameByIndex( ULONG index )
|
|||||||
ULONG UdtTypeInfo::getFieldCount()
|
ULONG UdtTypeInfo::getFieldCount()
|
||||||
{
|
{
|
||||||
if ( m_fields.empty() )
|
if ( m_fields.empty() )
|
||||||
getFields( m_dia );
|
{
|
||||||
|
getFields( m_dia, pyDia::SymbolPtr() );
|
||||||
|
getVirtualFields();
|
||||||
|
}
|
||||||
|
|
||||||
return (ULONG)m_fields.size();
|
return (ULONG)m_fields.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void UdtTypeInfo::getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset )
|
void UdtTypeInfo::getFields(
|
||||||
|
pyDia::SymbolPtr &rootSym,
|
||||||
|
pyDia::SymbolPtr &baseVirtualSym,
|
||||||
|
ULONG startOffset,
|
||||||
|
LONG virtualBasePtr,
|
||||||
|
ULONG virtualDispIndex,
|
||||||
|
ULONG virtualDispSize )
|
||||||
{
|
{
|
||||||
ULONG childCount = rootSym->getChildCount();
|
ULONG childCount = rootSym->getChildCount();
|
||||||
|
|
||||||
@ -536,18 +580,29 @@ void UdtTypeInfo::getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset )
|
|||||||
{
|
{
|
||||||
if ( !childSym->isVirtualBaseClass() )
|
if ( !childSym->isVirtualBaseClass() )
|
||||||
{
|
{
|
||||||
getFields( childSym, startOffset + childSym->getOffset() );
|
getFields( childSym, pyDia::SymbolPtr(), startOffset + childSym->getOffset() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if ( symTag == SymTagData )
|
if ( symTag == SymTagData )
|
||||||
{
|
{
|
||||||
TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, childSym );
|
TypeInfoPtr ti = TypeInfo::getTypeInfo( rootSym, childSym );
|
||||||
|
|
||||||
switch ( childSym->getDataKind() )
|
switch ( childSym->getDataKind() )
|
||||||
{
|
{
|
||||||
case DataIsMember:
|
case DataIsMember:
|
||||||
|
|
||||||
|
if ( baseVirtualSym )
|
||||||
|
{
|
||||||
|
ti->setVirtualBase(
|
||||||
|
TypeInfo::getTypeInfo(baseVirtualSym),
|
||||||
|
virtualBasePtr,
|
||||||
|
virtualDispIndex,
|
||||||
|
virtualDispSize );
|
||||||
|
}
|
||||||
|
|
||||||
ti->setOffset( startOffset + childSym->getOffset() );
|
ti->setOffset( startOffset + childSym->getOffset() );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DataIsStaticMember:
|
case DataIsStaticMember:
|
||||||
@ -560,12 +615,38 @@ void UdtTypeInfo::getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset )
|
|||||||
else
|
else
|
||||||
if ( symTag == SymTagVTable )
|
if ( symTag == SymTagVTable )
|
||||||
{
|
{
|
||||||
TypeInfoPtr ti = TypeInfo::getTypeInfo( m_dia, childSym );
|
if ( !baseVirtualSym )
|
||||||
|
{
|
||||||
|
TypeInfoPtr ti = TypeInfo::getTypeInfo( rootSym, childSym );
|
||||||
|
|
||||||
m_fields.push_back( std::make_pair( "__VFN_table", ti ) );
|
m_fields.push_back( std::make_pair( "__VFN_table", ti ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void UdtTypeInfo::getVirtualFields()
|
||||||
|
{
|
||||||
|
ULONG childCount = m_dia->getChildCount<SymTagBaseClass>();
|
||||||
|
|
||||||
|
for ( ULONG i = 0; i < childCount; ++i )
|
||||||
|
{
|
||||||
|
pyDia::SymbolPtr childSym = m_dia->getChildByIndex( i );
|
||||||
|
|
||||||
|
if ( !childSym->isVirtualBaseClass() )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
getFields(
|
||||||
|
childSym,
|
||||||
|
childSym,
|
||||||
|
0,
|
||||||
|
childSym->getVirtualBasePointerOffset(),
|
||||||
|
childSym->getVirtualBaseDispIndex(),
|
||||||
|
childSym->getVirtualBaseDispSize() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -587,6 +668,16 @@ std::string UdtTypeInfo::print()
|
|||||||
sstr << " " << std::left << std::setw(18) << std::setfill(' ') << getFieldNameByIndex(i) << ':';
|
sstr << " " << std::left << std::setw(18) << std::setfill(' ') << getFieldNameByIndex(i) << ':';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if ( fieldType->isVirtualMember() )
|
||||||
|
{
|
||||||
|
ULONG virtualBasePtr, virtualDispIndex, virtualDispSize;
|
||||||
|
fieldType->getVirtualDisplacement( virtualBasePtr, virtualDispIndex, virtualDispSize );
|
||||||
|
|
||||||
|
sstr << " virtual base " << fieldType->getVirtualBase()->getName();
|
||||||
|
sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset();
|
||||||
|
sstr << " " << getFieldNameByIndex(i) << ':';
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset();
|
sstr << " +" << std::right << std::setw(4) << std::setfill('0') << std::hex << fieldType->getOffset();
|
||||||
sstr << " " << std::left << std::setw(24) << std::setfill(' ') << getFieldNameByIndex(i) << ':';
|
sstr << " " << std::left << std::setw(24) << std::setfill(' ') << getFieldNameByIndex(i) << ':';
|
||||||
|
@ -42,12 +42,15 @@ public:
|
|||||||
m_offset( 0 ),
|
m_offset( 0 ),
|
||||||
m_staticOffset( 0 ),
|
m_staticOffset( 0 ),
|
||||||
m_constant( false ),
|
m_constant( false ),
|
||||||
m_staticMember( false )
|
m_staticMember( false ),
|
||||||
|
m_virtualMember( false ),
|
||||||
|
m_virtualBasePtr( 0 ),
|
||||||
|
m_virtualDispIndex( 0 ),
|
||||||
|
m_virtualDispSize( 0 )
|
||||||
{
|
{
|
||||||
m_constantValue.vt = VT_EMPTY;
|
m_constantValue.vt = VT_EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual std::string print() {
|
virtual std::string print() {
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
sstr << "Type name: " << getName();
|
sstr << "Type name: " << getName();
|
||||||
@ -125,10 +128,6 @@ public:
|
|||||||
throw TypeException( getName(), "type is not a pointer" );
|
throw TypeException( getName(), "type is not a pointer" );
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG getOffset() const {
|
|
||||||
return (ULONG)m_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOffset( ULONG offset ) {
|
void setOffset( ULONG offset ) {
|
||||||
m_offset = offset;
|
m_offset = offset;
|
||||||
}
|
}
|
||||||
@ -138,7 +137,6 @@ public:
|
|||||||
m_constant = true;
|
m_constant = true;
|
||||||
m_constantValue = var;
|
m_constantValue = var;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isConstant() const
|
bool isConstant() const
|
||||||
{
|
{
|
||||||
return m_constant == true;
|
return m_constant == true;
|
||||||
@ -149,19 +147,40 @@ public:
|
|||||||
return m_staticMember == true;
|
return m_staticMember == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isVirtualMember() const
|
||||||
|
{
|
||||||
|
return m_virtualMember == true;
|
||||||
|
}
|
||||||
|
|
||||||
void setStaticOffset( ULONG64 offset ) {
|
void setStaticOffset( ULONG64 offset ) {
|
||||||
m_staticOffset = offset;
|
m_staticOffset = offset;
|
||||||
m_staticMember = true;
|
m_staticMember = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG64 getStaticOffset() const {
|
void setVirtualBase( TypeInfoPtr virtualBase, LONG virtualBasePtr, ULONG virtualDispIndex, ULONG virtualDispSize )
|
||||||
return m_staticOffset;
|
{
|
||||||
|
m_virtualMember = true;
|
||||||
|
m_virtualBaseType = virtualBase;
|
||||||
|
m_virtualBasePtr = virtualBasePtr;
|
||||||
|
m_virtualDispIndex = virtualDispIndex;
|
||||||
|
m_virtualDispSize = virtualDispSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG64 getTypeOffset() const {
|
ULONG64 getTypeOffset();
|
||||||
return m_staticMember ? m_staticOffset : m_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
ULONG getOffset();
|
||||||
|
|
||||||
|
ULONG64 getStaticOffset();
|
||||||
|
|
||||||
|
void getVirtualDisplacement( ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) {
|
||||||
|
virtualBasePtr = m_virtualBasePtr;
|
||||||
|
virtualDispIndex = m_virtualDispIndex;
|
||||||
|
virtualDispSize = m_virtualDispSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeInfoPtr getVirtualBase() {
|
||||||
|
return m_virtualBaseType;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -181,7 +200,17 @@ protected:
|
|||||||
|
|
||||||
bool m_staticMember;
|
bool m_staticMember;
|
||||||
|
|
||||||
|
bool m_virtualMember;
|
||||||
|
|
||||||
VARIANT m_constantValue;
|
VARIANT m_constantValue;
|
||||||
|
|
||||||
|
LONG m_virtualBasePtr;
|
||||||
|
|
||||||
|
ULONG m_virtualDispIndex;
|
||||||
|
|
||||||
|
ULONG m_virtualDispSize;
|
||||||
|
|
||||||
|
TypeInfoPtr m_virtualBaseType;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -290,7 +319,16 @@ protected:
|
|||||||
|
|
||||||
FieldList m_fields;
|
FieldList m_fields;
|
||||||
|
|
||||||
void getFields( pyDia::SymbolPtr &rootSym, ULONG startOffset = 0 );
|
void getFields(
|
||||||
|
pyDia::SymbolPtr &rootSym,
|
||||||
|
pyDia::SymbolPtr &baseVirtualSym,
|
||||||
|
ULONG startOffset = 0,
|
||||||
|
LONG virtualBasePtr = 0,
|
||||||
|
ULONG virtualDispIndex = 0,
|
||||||
|
ULONG m_virtualDispSize = 0 );
|
||||||
|
|
||||||
|
|
||||||
|
void getVirtualFields();
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -248,7 +248,6 @@ class TypedVarTest( unittest.TestCase ):
|
|||||||
|
|
||||||
def testDiamondVirtualInherit(self):
|
def testDiamondVirtualInherit(self):
|
||||||
tv = pykd.typedVar( "g_virtChild" )
|
tv = pykd.typedVar( "g_virtChild" )
|
||||||
print tv
|
|
||||||
self.assertEqual( -100, tv.m_baseField )
|
self.assertEqual( -100, tv.m_baseField )
|
||||||
|
|
||||||
def testDinkumwareMap(self):
|
def testDinkumwareMap(self):
|
||||||
|
@ -335,10 +335,12 @@ public:
|
|||||||
virtual void virtFunc2() {}
|
virtual void virtFunc2() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class VirtualChildClass : public VirtualBaseClass1, public VirtualBaseClass2, public virtual classBase
|
class VirtualChildClass : public VirtualBaseClass1, public VirtualBaseClass2
|
||||||
{
|
{
|
||||||
void virtFunc() {}
|
void virtFunc() {}
|
||||||
void virtFunc2() {}
|
void virtFunc2() {}
|
||||||
|
|
||||||
|
void virtual virtFunc3() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
VirtualChildClass g_virtChild;
|
VirtualChildClass g_virtChild;
|
||||||
@ -426,7 +428,7 @@ void FuncWithName0()
|
|||||||
|
|
||||||
std::cout << g_structTypeDef.m_field0;
|
std::cout << g_structTypeDef.m_field0;
|
||||||
|
|
||||||
std::cout << g_virtChild.VirtualBaseClass1::m_baseField;
|
//std::cout << g_virtChild.VirtualBaseClass1::m_baseField;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user