Alternate picking virtual bases to share vptrs.
Coleen Phillimore
coleen at zko.dec.com
Thu Jan 13 19:59:29 UTC 2000
/*
Jason had a good point about virtual base dominators, since (below)
Concrete1 dominates Interface1,2,and 3, it appears that virtual function
calls to 'foo' first convert to a Concrete1 before being called. So in
this case, there's no point in sharing the vptr of Interface1 2 or 3
with the Most_Derived class. (Correct me if I'm wrong about this
please, this is all experimental).
The alternate algorithm could then be:
Pick the first virtual base class in dfs order (I vote no
declaration order on the base class specifier list) that's not a
primary base class of any subobject of derived class to be
the primary base class of the derived class. If there is no such
virtual base class, don't pick one.
I like dfs (depth first search) order because it's how our representation
stores them - it's painfully (and surprisingly) difficult to get back to
the order on the base class specifier list after it's parsed.
I just implemented this, it's pretty simple.
Test case for sharing virtual bases. In Most_Derived, share the vptr with
Interface2 but not Interface3, since Interface3 is indirectly inherited.
Should get:
(long)(Interface1 *)dd - (long)dd = 8
(long)(Interface2 *)dd - (long)dd = 8
(long)(Interface3 *)dd - (long)dd = 8
(long)(Interface4 *)dd - (long)dd = 0
(long)(Concrete1 *)dd - (long)dd = 8
*/
struct Interface1 {
virtual void foo();
};
struct Interface2 : virtual Interface1 {
virtual void foo();
};
struct Interface3 : virtual Interface2 {
virtual void foo();
};
struct Interface4 {
virtual void foo();
};
struct Concrete1 : virtual Interface3, virtual Interface4 {
virtual void foo();
int i; // important.
};
struct Most_Derived : virtual Interface1,
virtual Interface2,
virtual Concrete1 {
virtual void bar();
};
void Interface1::foo() {}
void Interface2::foo() {}
void Interface3::foo() {}
void Interface4::foo() {}
void Concrete1::foo() {}
void Most_Derived::bar() {}
extern "C" int printf(const char *,...);
#define EVAL(EXPR) printf( #EXPR " = %d\n", (EXPR) );
main()
{
Most_Derived *dd = new Most_Derived;
EVAL((long)(Interface1 *)dd - (long)dd);
EVAL((long)(Interface2 *)dd - (long)dd);
EVAL((long)(Interface3 *)dd - (long)dd);
EVAL((long)(Interface4 *)dd - (long)dd);
EVAL((long)(Concrete1 *)dd - (long)dd);
dd->foo();
}
More information about the cxx-abi-dev
mailing list