编译时检查基类是否为"接口"

Compile time check whether a base class is "interface"

本文关键字:接口 是否 基类 检查 编译      更新时间:2023-10-16

事实证明,如果没有涉及C++11,我最初想要的可能是不可能的,我想稍微改变一下需求,并询问您是否可以实现这一点。

上一个问题

基本上,我想在编译时检查一个类是否从"接口"继承。我所说的接口是指只使用纯虚拟方法的类。我想做以下代码:

template <typename T>
class Impl : public T {
public:
STATIC_ASSERT_INTERFACE(T);
};

这里的行为是,如果T只有纯虚拟方法,那么它将编译,如果它的一个方法没有,那么它就会失败。

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

这基本上类似于Java接口。在C++中,interface本身并不存在,它只是用于具有所有纯虚拟方法和仅static const数据成员的class的术语。

此外,纯虚拟方法可以具有功能体,也可以不具有功能体。因此,C++纯虚拟方法与Java的抽象方法并不完全相同。

不幸的是,您所要求的是不可能在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);

我几乎百分之百肯定你无法阻止别人这么做。

尽管我不确定自己是否同意这种做事方式,但你可以确保没有成员变量。制作一个空类,然后执行static_assert(sizeof(InterfaceClass) == sizeof(Empty))。我不确定假设尺寸为0是否安全——对于更熟悉标准的人来说,这是一个问题。

正如其他人已经解释的那样,你想要的东西不能直接完成。

然而,您仍然可以通过界面开发人员的一些规范来获得您想要的行为。如果所有接口都派生自一个公共基类Interface,则可以使用类似于此问题的技术在编译时检查Interface是否为基类。

例如:

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派生。这就是为什么我说它需要开发人员的一些纪律。

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