如果调用未重写的虚方法,如何强制编译器错误?

Eos*_*ern 6 c++ inheritance templates compiler-errors pragma

在C++中编写模板基类时,这是一个关于样式和安全性的相当普遍的问题.但是,请耐心等待,最后有一个具体问题......

我有一个模板基类,当类型T是基本类型(int,float等)时,它完全实现了所需的功能.但是,如果T不是原始的(例如,如果T是需要使用一组特定参数调用的构造函数的类),则需要覆盖某些方法,因此将它们声明为虚拟模板.模板还包含一个纯虚方法,它强制它是抽象的,所以为了使用它必须从以下派生:基于基本类型的派生类可以使用提供的所有方法并仅覆盖纯虚拟方法,而基于非基本类型的派生类应覆盖所有虚方法.

例如:

template <typename T> class myTemplate
{
public:
    // Constructor:
    myTemplate<T>();

    // Destructor:
    virtual ~myTemplate();

    // General function, valid for all classes derived from this:
    void printMe()
    {
        printf("Hello, I'm from the template\r\n");
    }

    // Primitive function, must be overridden for non-primitive types:
    virtual T DoSomething(const T& myClass)
    {
        T result = result + static_cast<T>(1);
        return result;
    }

    // Primitive function, must be overridden for non-primitive types:
    virtual T DoSomethingElse(const T& myClass)
    {
        T result = result - static_cast<T>(1);
        return result;
    }

    // Pure Virtual function, must be overridden in all cases:
    virtual void RefrainFromDoingAnythingAtAll(const T& myClass) = 0
};


class myIntegerClass : public myTemplate<int>
{
public:
    virtual void RefrainFromDoingAnythingAtAll(const int& myInteger) {} 
};
Run Code Online (Sandbox Code Playgroud)

假设现在我想创建一个派生类,我希望在其中调用"DoSomething",但不能设想"DoSomethingElse"有用的任何情况.因此,我想重新实现'DoSomething',但不要打扰'DoSomethingElse'.然而,如果在某一点上派生类的"DoSomethingElse"的方法被调用(或者是因为我真正的意思称之为"的DoSomething",但误写错误的事情,或者是因为一种情况出现,我此前没有设想),然后我希望发出编译器警告,提醒我除非我首先重新实现'DoSomethingElse',否则我不能这样做.

例如:

class myWatermelonClass : public myTemplate<Watermelon>
{
public:
    virtual Watermelon DoSomething(const Watermelon &myWatermelon)
    {
          // Just return a copy of the original:
          Watermelon anotherWatermelon(myWatermelon);
          return anotherWatermelon;
    }

    virtual Watermelon DoSomethingElse(const Watermelon &myWatermelon)
    {
          // This routine shouldn't ever get called: if it does, then 
          // either I've made an error or, if I find that I really need
          // to reimplement it after all, then I'd better buckle down
          // and do it.
          < How do I make the compiler remind me of this? >
    }        

    virtual void RefrainFromDoingAnythingAtAll(const Watermelon& myWatermelon) {}   
};
Run Code Online (Sandbox Code Playgroud)

显然我知道标准的#error和#warning编译器指令,但如果我使用其中一个,那么每次编译时都会标记错误(或警告).我想要的是确保在编译时如果我疏忽打电话给出错误

DoSomethingElse(aSpecificWatermelon);
Run Code Online (Sandbox Code Playgroud)

从我的代码中的某个地方,但不是.有没有办法实现这个目标?或者这首先是一个根本不好的设计?

gwi*_*rrr 2

我认为您滥用了模板和虚拟调度组合。例如,您的基类不会针对任何不支持加法运算符且可从 int 构造的类型进行编译。每次myTemplate隐式专门化时,所有虚拟函数都将被编译,即使您在派生类中重写它们:

virtual T DoSomething(const T& myClass)
{
    T result = result + static_cast<T>(1); // compile error when T == Watermelon
    return result;
}
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您正在寻找的是显式模板专业化:

template <>
class myTemplate<Watermelon>
{
public:
    // General function, valid for all classes derived from this:
    void printMe()
    {
        printf("Hello, I'm from the Watermelon template specialisation\r\n");
    }

    virtual Watermelon DoSomething(const Watermelon &myWatermelon)
    {
        // Just return a copy of the original:
        Watermelon anotherWatermelon(myWatermelon);
        return anotherWatermelon;
    }

    // notice there's no DoSomethingElse!

    virtual void RefrainFromDoingAnythingAtAll(const Watermelon& myWatermelon) {}   
};
Run Code Online (Sandbox Code Playgroud)

现在调用DoSomethingElse的实例myTemplate<Watermelon>将立即给出编译错误,因为没有这样的函数。