Interface implementation

G

Galian

Hi all. I have some questions about interface implementation, if
anybody can help me, I will be very thank.
So:

If i have some interface IA:

class IA
{
virtual void SomePureVirtFunc() = 0;
};

and some class B, that implemented that interface:

class B : public IA
{
virtual void SomePureVirtFunc() {};
};

Now I need in class C inherit from interface ITwoInOne, that inherited
from IA also.
Question: it is any method, inherit from interface ITwoInOne, and
don't implement interface IA, but using multiple inheritance - inherit
from class B, that already implemented that interface, and satisfy my
requirements?

Another words: can I write something like that:

class NewOne : public B
, public ITwoInOne
{
//Implementation only pure virtual functions
//, that not correspond to IA interface
}

P.S. sorry for confusion, and for my bad English.
 
V

Victor Bazarov

Galian said:
Hi all. I have some questions about interface implementation, if
anybody can help me, I will be very thank.
So:

If i have some interface IA:

class IA
{
virtual void SomePureVirtFunc() = 0;
};

and some class B, that implemented that interface:

class B : public IA
{
virtual void SomePureVirtFunc() {};
};

Now I need in class C inherit from interface ITwoInOne, that inherited
from IA also.
Question: it is any method, inherit from interface ITwoInOne, and
don't implement interface IA, but using multiple inheritance - inherit
from class B, that already implemented that interface, and satisfy my
requirements?

Yes, inherit from IA _virtually_ *everywhere*. I.e. make B inherit from
IA virtually and make ITwoInOne inherit virtually.
Another words: can I write something like that:

class NewOne : public B
, public ITwoInOne
{
//Implementation only pure virtual functions
//, that not correspond to IA interface
}

P.S. sorry for confusion, and for my bad English.

V
 
G

Galian

Yes, inherit from IA _virtually_ *everywhere*. I.e. make B inherit from
IA virtually and make ITwoInOne inherit virtually.

So this is right way:

class B : public virtual IA
{

};

class NewOne : public virtual B
, public virtual ITwoInOne
{

};

Is this right?
If yes, than question: is order of classes for inheritance important?
I mean it is OK if I write first "public virtual ITwoInOne", and than
"public virtual B"?
 
V

Victor Bazarov

Galian said:
So this is right way:

class B : public virtual IA
{

};

class NewOne : public virtual B
, public virtual ITwoInOne
{

};

Is this right?
If yes, than question: is order of classes for inheritance important?
I mean it is OK if I write first "public virtual ITwoInOne", and than
"public virtual B"?

I think that the order is not significant. Have you tried it? If you
have, and the success depended on the order, could you please share?
If you haven't tried, why?

V
 
G

Galian

I have tried, and it don't work. "Cannot instantiate abstract class"
error. I don't now why. I tried different order, but it don't help.
Thank you Victor for the answers.
 
V

Victor Bazarov

Galian said:
I have tried, and it don't work. "Cannot instantiate abstract class"
error. I don't now why. I tried different order, but it don't help.

Sounds like FAQ 5.8 should help. Check it out. It also can be that
your compiler is not capable; we'll know as you check out the FAQ.
Thank you Victor for the answers.

You're most welcome.

V
 
G

Galian

Victor Bazarov :
Sounds like FAQ 5.8 should help. Check it out. It also can be that
your compiler is not capable; we'll know as you check out the FAQ.


You're most welcome.

V

Sorry Victor, but about what FAQ you talking? Where can I find it?
 
G

Galian

Sorry Victor, but about what FAQ you talking? Where can I find it?

Wow, I understand :) sorry.

This is my code. Task is next: I want write template class, CUnknown,
with implemented nessesary methods (Queryinterface, Release ...), to
use it for other classes.

CUnknown:

template < class ClassType, REFIID ObjectIID >
class CUnknown : public IUnknown
{
protected:
// IUnknown methods.
virtual STDMETHODIMP QueryInterface( REFIID riid, void** ppv )
{
if ( ppv == NULL )
{
return E_POINTER;
}
if ( riid == *ObjectIID || riid == IID_IUnknown )
{
*ppv = static_cast< ClassType* >( this );
AddRef();
return S_OK;
}
*ppv = NULL;
return E_NOINTERFACE;
}

virtual STDMETHODIMP_( ULONG ) AddRef()
{
return InterlockedIncrement( &m_cRef );
}

virtual STDMETHODIMP_( ULONG ) Release()
{
LSCOPE( "CMediaBuffer::Release" );
LONG lRef = InterlockedDecrement( &m_cRef );
if ( lRef == 0 )
{
delete this;

// m_cRef is no longer valid! Return lRef.
}
return lRef;
}

LONG m_cRef;
};

#include "Unknown.h"

class ISMSNotificationHandler
{
public:
virtual void HandleSMSMessageReceived( const CEOID messageID ) = 0;
};

// IMAPIAdviseSink also derived from IUnknown

class CAdviseSinc
// This is my CUnknown,but anyway "Cannot instantiate abstract
class" error
: public virtual CUnknown< CAdviseSinc, IID_IMAPIAdviseSink >
, public virtual IMAPIAdviseSink
{
public:
CAdviseSinc();
~CAdviseSinc();

private:
ULONG OnNotify( ULONG cNotif, LPNOTIFICATION lpNotifications );
};

Actually in this group yes, but not in other, I am sorry.
 
V

Victor Bazarov

Galian said:
[..]
This is my code. Task is next: I want write template class, CUnknown,
with implemented nessesary methods (Queryinterface, Release ...), to
use it for other classes.

CUnknown:

template < class ClassType, REFIID ObjectIID >
class CUnknown : public IUnknown

What's "IUnknown"? Are we supposed to know about it? (pun intended)
I am guessing that it's the base interface you have and it's abstract.
{
protected:
// IUnknown methods.
virtual STDMETHODIMP QueryInterface( REFIID riid, void** ppv )
{
if ( ppv == NULL )
{
return E_POINTER;
}
if ( riid == *ObjectIID || riid == IID_IUnknown )
{
*ppv = static_cast< ClassType* >( this );
AddRef();
return S_OK;
}
*ppv = NULL;
return E_NOINTERFACE;
}

virtual STDMETHODIMP_( ULONG ) AddRef()
{
return InterlockedIncrement( &m_cRef );
}

virtual STDMETHODIMP_( ULONG ) Release()
{
LSCOPE( "CMediaBuffer::Release" );
LONG lRef = InterlockedDecrement( &m_cRef );
if ( lRef == 0 )
{
delete this;

// m_cRef is no longer valid! Return lRef.
}
return lRef;
}

LONG m_cRef;
};

#include "Unknown.h"

I am guessing that's where your 'class CUnknown' is defined, or is it?
class ISMSNotificationHandler
{
public:
virtual void HandleSMSMessageReceived( const CEOID messageID ) = 0;
};

// IMAPIAdviseSink also derived from IUnknown

class CAdviseSinc
// This is my CUnknown,but anyway "Cannot instantiate abstract
class" error

Does it say what function prevents it from being instantiated?
, public virtual IMAPIAdviseSink
{
public:
CAdviseSinc();
~CAdviseSinc();

private:
ULONG OnNotify( ULONG cNotif, LPNOTIFICATION lpNotifications );
};

OK. Try to change the beginning of the definition of 'CUnknown' to

template < class ClassType, REFIID ObjectIID >
class CUnknown : virtual public IUnknown
^^^^^^^

Also, do the same with IMAPIAdviseSink. What you're doing is telling
the compiler that some pure virtual functions in your 'CAdviseSink'
only exist in a single base class instance and that they are happily
overridden by the corresponding functions in 'CUnknown<blah,blah>'.

V
 
G

Galian

Ok, this is my code now:

//CUnknow class

template < class ClassType, REFIID ObjectIID >
class CUnknown : public IUnknown
{
protected:
// IUnknown methods.
virtual STDMETHODIMP QueryInterface( REFIID riid, void** ppv )
{
if ( ppv == NULL )
{
return E_POINTER;
}
if ( riid == ObjectIID || riid == IID_IUnknown )
{
*ppv = reinterpret_cast< ClassType* >( this );
AddRef();
return S_OK;
}
*ppv = NULL;
return E_NOINTERFACE;
}

virtual STDMETHODIMP_( ULONG ) AddRef()
{
return InterlockedIncrement( &m_cRef );
}

virtual STDMETHODIMP_( ULONG ) Release()
{
LONG lRef = InterlockedDecrement( &m_cRef );
if ( lRef == 0 )
{
delete this;
// m_cRef is no longer valid! Return lRef.
}
return lRef;
}

LONG m_cRef;
};

// IMAPIAdviseSink also derived from IUnknown

class CAdviseSinc
: public virtual CUnknown< CAdviseSinc, IID_IMAPIAdviseSink >
, public virtual IMAPIAdviseSink
{
public:
CAdviseSinc() {};
~CAdviseSinc() {};

private:

ULONG OnNotify( ULONG cNotif, LPNOTIFICATION lpNotifications )
{ return 0; }
};

Now,if I try to create instance of class CAdviseSinc, i have this
message:

error C2259: 'CAdviseSinc' : cannot instantiate abstract class
due to following members:
'HRESULT IMAPIAdviseSink::QueryInterface(const IID &,LPVOID
*)' : is abstract
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0
Pocket PC SDK\include\ARMV4I\mapidefs.h(889) : see declaration of
'IMAPIAdviseSink::QueryInterface'
'ULONG IMAPIAdviseSink::AddRef(void)' : is abstract
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0
Pocket PC SDK\include\ARMV4I\mapidefs.h(889) : see declaration of
'IMAPIAdviseSink::AddRef'
'ULONG IMAPIAdviseSink::Release(void)' : is abstract
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0
Pocket PC SDK\include\ARMV4I\mapidefs.h(889) : see declaration of
'IMAPIAdviseSink::Release'

but this three methods are implemented in CUnknown.
 
V

Victor Bazarov

Galian said:
Ok, this is my code now:

//CUnknow class

template < class ClassType, REFIID ObjectIID >
class CUnknown : public IUnknown

I am sorry to sound a bit irritated, but didn't I just tell
you to use virtual inheritance *here* AND in the *definition*
of 'IMAPIAdviseSink'? You decided NOT TO follow that and
instead derived virtualy *from* 'IMAPIAdviseSink'. Am I just
being unclear somehow?
{
protected:
// IUnknown methods.
virtual STDMETHODIMP QueryInterface( REFIID riid, void** ppv )
{
if ( ppv == NULL )
{
return E_POINTER;
}
if ( riid == ObjectIID || riid == IID_IUnknown )
{
*ppv = reinterpret_cast< ClassType* >( this );
AddRef();
return S_OK;
}
*ppv = NULL;
return E_NOINTERFACE;
}

virtual STDMETHODIMP_( ULONG ) AddRef()
{
return InterlockedIncrement( &m_cRef );
}

virtual STDMETHODIMP_( ULONG ) Release()
{
LONG lRef = InterlockedDecrement( &m_cRef );
if ( lRef == 0 )
{
delete this;
// m_cRef is no longer valid! Return lRef.
}
return lRef;
}

LONG m_cRef;
};

// IMAPIAdviseSink also derived from IUnknown

class CAdviseSinc
, public virtual IMAPIAdviseSink
{
public:
CAdviseSinc() {};
~CAdviseSinc() {};

private:

ULONG OnNotify( ULONG cNotif, LPNOTIFICATION lpNotifications )
{ return 0; }
};

Now,if I try to create instance of class CAdviseSinc, i have this
message:

error C2259: 'CAdviseSinc' : cannot instantiate abstract class
due to following members:
'HRESULT IMAPIAdviseSink::QueryInterface(const IID &,LPVOID
*)' : is abstract
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0
Pocket PC SDK\include\ARMV4I\mapidefs.h(889) : see declaration of
'IMAPIAdviseSink::QueryInterface'
'ULONG IMAPIAdviseSink::AddRef(void)' : is abstract
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0
Pocket PC SDK\include\ARMV4I\mapidefs.h(889) : see declaration of
'IMAPIAdviseSink::AddRef'
'ULONG IMAPIAdviseSink::Release(void)' : is abstract
C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0
Pocket PC SDK\include\ARMV4I\mapidefs.h(889) : see declaration of
'IMAPIAdviseSink::Release'

but this three methods are implemented in CUnknown.

V
 
G

Galian

Victor Bazarov :
I am sorry to sound a bit irritated, but didn't I just tell
you to use virtual inheritance *here* AND in the *definition*
of 'IMAPIAdviseSink'? You decided NOT TO follow that and
instead derived virtualy *from* 'IMAPIAdviseSink'. Am I just
being unclear somehow?

Sorry I forgot it, fixed, now CUnknown look like it:

template < class ClassType, REFIID ObjectIID >
class CUnknown : public virtual IUnknown
{
..
..
..
but error message the same as before
 
V

Victor Bazarov

Galian said:
Victor Bazarov :

Sorry I forgot it, fixed, now CUnknown look like it:

template < class ClassType, REFIID ObjectIID >
class CUnknown : public virtual IUnknown
{
.
.
.
but error message the same as before

OK. Let's put your code aside for a minute. Try the following:
------------------
class I { virtual void foo() = 0; };
class C : virtual public I { void foo() {} };
class II : virtual public I {};
class CC : public C, public II {};

int main() {
CC cc;
}
------------------
Does it compile with your compiler? If it doesn't, your compiler is
non-compliant and you will have to work around its shortcomings. You
will need to re-implement the "offending" functions in the final class
and in them simply call the one you want to work as the overrider.

If the code does compile, please study it and make the necessary changes
to *your* code.

V
 
G

Galian

Victor Bazarov :
OK. Let's put your code aside for a minute. Try the following:
------------------
class I { virtual void foo() = 0; };
class C : virtual public I { void foo() {} };
class II : virtual public I {};
class CC : public C, public II {};

int main() {
CC cc;
}
------------------
Does it compile with your compiler? If it doesn't, your compiler is
non-compliant and you will have to work around its shortcomings. You
will need to re-implement the "offending" functions in the final class
and in them simply call the one you want to work as the overrider.

If the code does compile, please study it and make the necessary changes
to *your* code.

V

Yes it compiled, only warning "warning C4250: 'CC' : inherits
'C::C::foo' via dominance
.\ConsoleSmart.cpp(45) : see declaration of 'C::foo'"

Thank you very much. Sorry for the trouble.
 
J

James Kanze

If ITwoInOne inherits from IA, it must also inherit virtually.
If NewOne is the most derived class, on the other hand, virtual
inheritance from B and from ITwoInOne is not necessary, although
it may be a good idea, in case someone later wants to inherit
from it. (In general, unless the inheritance tree is closed,
most inhertance should be virtual.)
I think that the order is not significant.

It affects the order in which constructors are called. In the
case of virtual base classes, the constructors are called from
the most derived class, "in the order they appear on a
depth-first left-to-right traversal of the directed acyclic
graph of base classes, where `left-to-right' is the order of
appearance of the base class names in the derived class
base-specifierlist."

It will also typically affect the actual layout, and may have
some effect on runtime, although I can't imagine this being
significant.
Have you tried it? If you
have, and the success depended on the order, could you please share?
If you haven't tried, why?

Note that trying it doesn't tell you anything about the
guarantee. The order you find might be because in the standard,
the order was implementation defined, or unspecified.
Experimentation is usually a pretty poor means of finding out
these sort of things; the poster is doing the right thing in
asking.
 
V

Victor Bazarov

James said:
Note that trying it doesn't tell you anything about the
guarantee.

No, but it gets him closer to _a_ solution so he can move onto more
important things in life than looking for guarantees.
The order you find might be because in the standard,
the order was implementation defined, or unspecified.

Is it?
Experimentation is usually a pretty poor means of finding out
these sort of things; the poster is doing the right thing in
asking.

<sigh> Maybe, in this particular case. I am not sure what you
mean by "these sort of things", though. WHAT sort of things?

I say, push that "compile" button without asking first, since
nothing bad can come out of it, really. There is no sense in
asking "will such and such code compile?" when you have a compiler
sitting right there. One could ask "_should_ such and such code
compile" or "is my compiler correct to {accept/reject} such and
such code", but I still don't see a reason not to try.

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top