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