我如何从一个 class 继承,因为我覆盖了一个函数而无法用某些模板参数实例化?

How can I inherit from a class that can't be instanciated with certain template parameters because of a function that I'm overriding?

我有一些类似于下面的代码:

#include <type_traits>

template <typename T>
class A
{
    virtual void failifint()
    {
        static_assert(!std::is_same<T, int>(), "T is an int!");
    }
};

class B : public A <int>
{
    virtual void failifint()
    {
        // Don't fail
    }
};

int main()
{
    B b ;
}

我希望任何包含 A<T> 对象的代码只要 T 不是 int 就可以编译,而包含 B 的代码编译,因为 failifint() 被覆盖为 int 可编译版本。但是,上述代码由于静态断言而失败,即使没有任何 A<int> 实例化。

为什么会这样?以及如何使用 failifint 的特殊实现创建 B,它不会因为在 A?

中的实现而在编译错误中失败

这里的问题是 static_assert 是一个 编译时 特性,它在编译期间检查条件,而虚函数 call/dispatch 在 运行-时间。编译器仍然必须编译基class中的函数,这将导致断言。

"However, the aforementioned code fails because of the static assertion even though there isn't any A instanciated."

但是有一个:通过B。B是A。

"And how can I create B with a special implementation of failifint that doesn't fail in a compilation error because of its implementation in A?"

你不能,只要 A 的 failifint 是虚拟的。你可以做的是覆盖它。只需删除 virtual 关键字即可。这将隐藏 A 的 failifint。

template <typename T>
class A
{
    public:
        void failifint()
        {
            static_assert(!std::is_same<T, int>(), "T is an int!");
            printf("A failifint\n");
        }
};

class B : public A <int>
{
    public:
        void failifint()
        {
            printf("B\n");
        }
};

如果在 main 中有以下代码,a.failifint 将给出编译时错误。

B b; A<int> a; b.failifint(); // B a.failifint(); //compile error

但是,如果您必须通过虚拟方法扩展 A 的 failifint 功能,您也可以这样做

// Abstract base
template <typename T>
class A
{
    public:
        virtual void failifint() = 0;
};

// Can be of type int
class B : public A <int>
{
    public:
        void failifint()
        {
            printf("B\n");
        }
};

// Anything deriving from C cannot be int
class C : public A <typename T>
{
    public:
        virtual void failifint()
        {
            static_assert(!std::is_same<T, int>(), "T is an int!");
            printf("C failifint\n");
        }
};

这将允许某些 A 对 int 抛出异常,而某些则不允许。如果它们直接派生自 A,那么你就很好。如果它们从 C 派生,则它们不能是 int 类型。

您的尝试确实有问题:

class A
{
    virtual void print() { cout << "A" << endl; }
    virtual ~A() { print(); }
}

class B : A
{
    virtual void print() { cout << "B" << endl; }
}

...

B b;

将在析构时打印 A,而不是 B。因此当您实例化 B 时,会实例化一个 A