Hi,

The following code compiles fine with VS 2003 but not with eVC4 SP4. I am
not sure VS.NET is right since the situation is kind of ambiguous.
Basically, we have a MultiEar class derive "twice" from the same IListener
interface - we do that by aliasing the interface with AListener and
BListener. Two separate vtables should be produced, but... eVC4 does not
seem to think so.

Here is the code:

// interiorListeners.cpp : Defines the entry point for the console
application.
//
/* this test investigates what happens when you need to have multiple
implementations of a base class in a derived class.
Questions:
Is this legal C++?
Is the intent of the syntax clear?
Should it work on all C++ compilers?
*/

#include "stdafx.h"
/** first declare a listener interface */
class IListener
{
public:
virtual void OnEvent(const char * name, int id)=0;
};
/* a class we can listen too */
class EventSource
{
public:
EventSource(const char * name) : m_name(name)
{
m_listener = NULL;
}

void fireEvent(int id)
{
if (m_listener)
m_listener->OnEvent(m_name, id);
}

void addListener(IListener* listener)
{
m_listener = listener;
}

private:
IListener* m_listener;
const char * m_name;
};

/* derived classes used to force the child to have specific
implementations for both versions of listener
*/
class AListener : public IListener
{
// implement IListener
virtual void OnEvent(const char * name, int id)=0;
};

class BListener : public IListener
{
// implement IListener
virtual void OnEvent(const char * name, int id)=0;
};

/* this class wishes to support both listeners with different
implementations
however the implementations need to be in the class scope in order
to access member vars without recourse to parent pointers and the like.
*/
class MultiEar
: public AListener, BListener
{
public:
MultiEar()
: a(_T("EventSource A"))
, b(_T("EventSource B"))
{
m_int = 0;
}

//* This code compiles and works ok on MSVC.NET but not on EVC4.
// implement IListener
void AListener::OnEvent(const char * name, int id)
{
printf(_T("%s %d AListener OnEvent(%s, %d)\n"), ClassName(), m_int,
name, id);
m_int++;
}

// implement IListener
void BListener::OnEvent(const char * name, int id)
{
printf(_T("%s %d BListener OnEvent(%s, %d)\n"), ClassName(), m_int, name,
id);
m_int++;
}

void Test()
{
a.addListener((AListener*)this);
b.addListener((BListener*)this);
a.fireEvent(1);
a.fireEvent(2);
b.fireEvent(1);
b.fireEvent(2);
}

private:
EventSource a, b;
const char * ClassName() { return _T("MultiEar") ; }
int m_int;
};

int _tmain(int argc, _TCHAR* argv[])
{
printf(_T("testing interior listener classes.\n"));
// create the MultiEar
MultiEar multiEar;
multiEar.Test();
return 0;
}

/** expected output
testing interior listener classes.
MultiEar 0 AListener OnEvent(EventSource A, 1)
MultiEar 1 AListener OnEvent(EventSource A, 2)
MultiEar 2 BListener OnEvent(EventSource B, 1)
MultiEar 3 BListener OnEvent(EventSource B, 2)
*/

Any idea?

Thanks!

Re: Code compiles with VS2003 but not eVC4 by Carl

Carl
Sun Aug 21 19:04:46 CDT 2005

"John Doe" <reply@togroup.please> wrote in message
news:O$Zu8jqpFHA.2904@TK2MSFTNGP12.phx.gbl...
> Hi,
>
> The following code compiles fine with VS 2003 but not with eVC4 SP4. I am
> not sure VS.NET is right since the situation is kind of ambiguous.
> Basically, we have a MultiEar class derive "twice" from the same IListener
> interface - we do that by aliasing the interface with AListener and
> BListener. Two separate vtables should be produced, but... eVC4 does not
> seem to think so.

VC7.1 is wrong (unless you're compiling managed C++, where I believe it is
legal), eVC4 is right. The code is not legal C++.

In order to separately override two inherited functions that have the same
signature, you need to use "trampoline" functions:

struct I
{
virtual void f() = 0;
};

struct A : public I
{
void f() { A_f(); }
virtual void A_f() = 0;
};

struct B : public I
{
void f() { B_f(); }
virtual void B_f() = 0;
};

struct AB : public A, public B
{
void A_f() { ... }
void B_f() { ... }
};

-cd