C++ 强制接收实现接口的超类指针作为方法的参数

C++ 强制接收实现接口的超类指针作为方法的参数,c++,inheritance,C++,Inheritance,我有一个超类a和几个子类(B,C,D…),其中一些类也是超类,所以这些类之间的关系有点复杂 现在,我介绍了一个接口类I,其中包含几个纯虚拟方法。该接口在一个应用程序的不同子类中实现 class A { }; class I { }; class B : public A, public I { }; class C : public A { }; class D : public C, public I { }; 我想调用一个作为参数接收指针的函数,因为该函数使用超类的功能。但是函数期

我有一个超类a和几个子类(B,C,D…),其中一些类也是超类,所以这些类之间的关系有点复杂

现在,我介绍了一个接口类I,其中包含几个纯虚拟方法。该接口在一个应用程序的不同子类中实现

class A { };

class I { };

class B : public A, public I { };

class C : public A { };

class D : public C, public I { };
我想调用一个作为参数接收指针的函数,因为该函数使用超类的功能。但是函数期望此参数也实现接口。在上面的示例中,函数应该只接受B和D类型

我正在使用动态强制转换检查此参数是否是I的指针

void f(A *obj)
{
    I *interface = dynamic_cast <I *>(obj);
    if (interface) ...
}
void f(A*obj)
{
I*接口=动态投影(obj);
如果(接口)。。。
}
<>但是我想知道C++是否允许我更好的解决方案,并且在编译时检查这个问题。
谢谢

如果您想要强制执行编译时限制,即
a
I
都是您传入的任何指针的基类,您可以使用和:

注意,
的基础允许
A
成为
T
的基础。如果您希望强制它是一个可访问的基础,您可以改为使用:

模板
typename std::启用\u如果<
标准::是否可转换::值&&
std::是否可转换::值
>::输入foo(T*T){
}
使用SFINAE:

template <typename T, typename = typename std::enable_if<std::is_base_of<A, T>::value && std::is_base_of<I, T>::value>::type >
void foo(T* t) 
{

}

这看起来好一点。

如果
a
是非多态类型,
a*
I*
的动态转换将不会编译。此外,由于您使用的是动态分派,我认为直到运行时,
obj
的动态类型才知道。所以,你可能走错了方向。实际上,重新设计类层次结构可能是解决问题的正确方法,而不是在OP中尝试做什么。举例说明:

class InterfaceOfA;
class I;
class AI: public InterfaceOfA, public I;
class A: public InterfaceOfA;
class B : public AI;
class C : public A;
class D : public C, public AI;
void f(AI *obj);

您可以考虑重新设计类层次结构。非常感谢。我不知道C++的这个特性。然而,这对我来说似乎很复杂。因为我的应用程序中有大量的类,所以不可能重新设计所有的类。我将使用实现接口的委托。委托应该是方法的第二个参数。因此,调用的第一个和第二个参数将指向同一个对象。我知道这个解决方案并不优雅。你怎么认为?
template <typename T>
typename std::enable_if<
    std::is_convertible<T*, A*>::value && 
    std::is_convertible<T*, I*>::value
>::type foo(T* t) {

}
template <typename T, typename = typename std::enable_if<std::is_base_of<A, T>::value && std::is_base_of<I, T>::value>::type >
void foo(T* t) 
{

}
template<typename D, typename B1, typename B2>
using extends = typename std::enable_of<std::is_base_of<B1,D>::value and std::is_base_of<B2,D>::value>::type;
template<typename T, typename = extends<T,A,I>> //T extends A and I.
void foo()
{
}
class InterfaceOfA;
class I;
class AI: public InterfaceOfA, public I;
class A: public InterfaceOfA;
class B : public AI;
class C : public A;
class D : public C, public AI;
void f(AI *obj);