C++ 编译时检查基类是否为;接口“;

C++ 编译时检查基类是否为;接口“;,c++,compilation,C++,Compilation,事实证明,我最初想要的可能不可能是涉及C++11的w/o,我想稍微更改一下需求,并询问您是否可以实现这一点 基本上,我想在编译时检查类是否从“接口”继承。我所说的接口是指仅具有纯虚拟方法的类。 我想执行以下代码: template <typename T> class Impl : public T { public: STATIC_ASSERT_INTERFACE(T); }; 模板 类Impl:public T{ 公众: 静态断言接口(T); }; 这里的行为是,如果T只有

事实证明,我最初想要的可能不可能是涉及C++11的w/o,我想稍微更改一下需求,并询问您是否可以实现这一点

基本上,我想在编译时检查类是否从“接口”继承。我所说的接口是指仅具有纯虚拟方法的类。 我想执行以下代码:

template <typename T>
class Impl : public T {
public:
STATIC_ASSERT_INTERFACE(T);
};
模板
类Impl:public T{
公众:
静态断言接口(T);
};
这里的行为是,如果T只有纯虚方法,那么它将编译,如果它的一个方法没有被编译,那么它将失败


有人能想到这样的东西吗?

这基本上类似于Java接口。在C++中,不存在“代码>接口”,它只是一个用于“<代码>类>代码>的术语,所有纯的虚拟方法,只有<代码>静态const < /C>数据成员。 此外,纯虚拟方法可能有也可能没有函数体。因此C++纯虚拟方法与java的抽象方法不完全相同。
<> P>不幸的是,你要问的是<强>不可能在C++中模拟。

首先,接口不是C++的原生概念。我相信大多数程序员都知道它们是什么,但编译器不知道,这就是你遇到问题的地方。C++可以做很多事情,我敢打赌你可以把它变成很多不同语言的样子,但是如果你要写C++,最好用C++的方式做。 还有一件事,这里有很多灰色地带。如果你像你建议的那样有一个“界面”,但有人做了其中一个:

// Technically not a member function, but still changes the behavior of that class.
bool operator==(const Interface &left, const Interface &right);
我几乎100%肯定你不能阻止别人这么做


您可以确保没有成员变量,尽管我不确定我是否同意这种方式。创建一个空类,然后执行
静态断言(sizeof(InterfaceClass)==sizeof(empty))
。我不确定假设大小为0是否安全-这是一个更熟悉标准的人的问题。

正如其他人已经解释的那样,您想要什么不能直接完成

但是,您仍然可以从接口开发人员那里获得所需的行为,只需遵守一些规则。如果所有接口都派生自一个公共基类
接口
,则可以使用类似于的技术在编译时检查
接口
是否为基类

例如:

class Interface {
    public :
        virtual ~Interface() { }
};

template <typename T>
struct IsDerivedFromInterface {
    static T t();
    static char check(const Interface&);
    static char (&check(...))[2];
    enum { valid = (sizeof(check(t())) == 1) };
};

class MyInterface : public Interface {
    public :
        virtual void foo() = 0;
};

class MyBase {
    public :
        virtual void bar() { }
};

class Foo : public MyInterface {
    public :
        virtual void foo() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Foo>::valid);    // just fine

class Bar : public MyBase {
    public :
        virtual void bar() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Bar>::valid);    // oops
类接口{
公众:
虚拟~Interface(){}
};
模板
结构IsDerivedFromInterface{
静态T();
静态字符检查(常量接口&);
静态字符(&检查(…)[2];
枚举{valid=(sizeof(check(t())==1)};
};
类MyInterface:公共接口{
公众:
虚拟void foo()=0;
};
类MyBase{
公众:
虚拟空栏(){}
};
类Foo:公共MyInterface{
公众:
虚拟void foo(){}
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface::valid);//很好
类栏:公共MyBase{
公众:
虚拟空栏(){}
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface::valid);//哎呀
当然,基类的开发人员可以欺骗并从
接口
派生,即使基类不是接口。这就是为什么我说它需要开发者的一些纪律


尽管如此,我看不出这有什么用处。我从来没有觉得我需要这种编译时检查。

真的所有方法都是纯虚拟的吗?即使是析构函数?大概你也要检查
T
是否也有基类,如果有,它们是否也是“接口”。但答案确实是“不”,永远不会是0。因为如果您声明多个类型为
Empty
的变量,那么每个变量在内存中都必须有一个唯一的地址。
static\u assert(sizeof(InterfaceClass)==sizeof(Empty))
-无法确定。类和空类的大小(没有成员变量和虚拟函数)将是1字节,
接口类的大小通常不会是1字节,最可能的是会有虚拟函数,它将使大小为4字节(指针大小)。基本上,我希望所有方法都是虚拟的,以确保覆盖它们(我不是说c'tor等…。@VadimS:你的意思是要确保覆盖所有方法,还是要确保当你编写一个应该覆盖基类方法的方法时,它确实覆盖了基类方法?我想避免(在编译时)我希望重写基类中的方法,但该方法未定义为“virtual”。