Verifying compile-time interface implementation in C ++

I use pseudo-interfaces in C ++, i.e. pure abstract classes. Suppose I have three interfaces: IFoo, IBar, and IQuux. I also have a Fred class that implements all three of them:

interface IFoo
{
    void foo (void);
}   

interface IBar
{
    void bar (void);
}

interface IQuux
{
    void quux (void);
}   

class Fred : implements IFoo, IBar, IQuux
{
}

I want to declare a method that accepts any object that implements IFoo and IBar - for example, Fred will work. The only way to do this, I can imagine, is to define a third IFooAndBar interface that implements both, and redeclare Fred:

interface IFooAndBar : extends IFoo, IBar
{   
}

class Fred : implements IFooAndBar, IQuux
{
}

Now I can declare my method as getting IFooAndBar *. So far so good.


However, what happens if I also need another method that accepts IBar and IQuux? I tried to declare a new IBarAndQuux interface and declare Fred as inheriting both:

class IFooAndBar : IFoo, IBar
{
};


class IBarAndQuux : IBar, IQuux
{
};


class Fred : IFooAndBar, IBarAndQuux
{
};

, Fred IFooAndBar ; , Fred:: bar(), gcc :

error: request for member ‘bar’ is ambiguous
error: candidates are: void IBar::bar()
error:                 void IBar::bar()

.


, Fred , :

class Fred : public IFoo, public IBar, public IBaz
{

};

void doTest (IBarAndBaz* pObj)
{
    pObj->bar();
    pObj->baz();
}

Fred IBarAndBaz *, , :

error: cannot convert ‘Fred*’ to ‘IBarAndBaz*’ for argument ‘1’ to ‘void doTest(IBarAndBaz*)’

dynamic_cast < > ( )

error: cannot dynamic_cast ‘pFred’ (of type ‘class Fred*’) to type ‘class IBarAndBaz*’ (source type is not polymorphic)

, :

doTest((IBarAndBaz*)pFred);

, ( Linux, Mac Windows) .


, , dynamic_cast (), , .

+5
4

- Boost.TypeTraits :

template<class T>
void takeFooAndBar(const T& t) {
    BOOST_STATIC_ASSERT(
           boost::is_base_of<IFoo, T>::value 
        && boost::is_base_of<IBar, T>::value);
    /* ... */
}
+6

OO, , , Fred IBar:

class IFooAndBar : public IFoo, public virtual IBar {};
class IBarAndQuux : public virtual IBar, public IQuux {};

class Fred : public IFooAndBar, public IBarAndQuux {};

Fred fred;
fred.bar(); // unambiguous due to virtual inheritence

, - , , .

, , , Fred IBarAndBaz. , , , , undefined.

. , , , , :

void doTest(IBar *bar, IBaz *baz)
{
    bar->bar();
    baz->baz();
}

class Fred : public IBar, public IBaz {};

Fred fred;
doTest(&fred,&fred);
+3

, :

tempate<class C>
void doTest( C* pObj )
{
  pObj->bar();
  pObj->baz();
}

, bar() baz(), .

+1

, , , , , .

struct IFoo 
{
    virtual void foo() = 0;
};

struct IBar 
{
    virtual void bar() = 0;
};

struct IFooAndBar : public IFoo, public IBar {};

class FooAndBarCompositor : public IFooAndBar
{
public:
    template <class T>
    FooAndBarCompositor(T* pImpl) : m_pFoo(pImpl), m_pBar(pImpl) {}

    void foo() {m_pFoo->foo();}
    void bar() {m_pBar->bar();}

private:
    IFoo* m_pFoo;
    IBar* m_pBar;
};

, IFooAndBar *, , FooAndBarCompositor , . :

void testFooAndBar(IFooAndBar* pI) {}

void baz(Fred* pFred)
{
    FooAndBarCompositor fb(pFred);
    testFooAndBar(&fb);
}

. , :

template <class IA, class IB>
class InterfaceCompositor
{
public:
    template <class T>
    InterfaceCompositor(T* pObj) : m_pIA(pObj), m_pIB(pObj) {}

    IA* AsA() const {return m_pIA;}
    operator IA* () const {return AsA();}
    IB* AsB() cosnt {return m_pIB;}
    operator IB* () const {return AsB();}

private:
    IA* m_pIA;
    IB* m_pIB;
};

:

void testFooAndBar(InterfaceCompositor<IFoo, IBar> pI)
{
    IFoo* pFoo = pI; // Or pI.AsA();
    IBar* pBar = pI; // Of pI.AsB();
}

, , A * B * (, ) AsX(). , → , * .

, , IBar, IBaz.

++ 0x , .

+1

All Articles