具有静态(内联)方法的从未实例化类的基类

时间:2014-01-28 10:07:10

标签: c++ static-methods

我有一堆类(我从未实例化)以不同的方式实现相同的静态内联方法。我试图了解这些类是否可以拥有共同的父级。 目的不是要进行虚拟调用,而只是为任何想要以不同方式再次编写实现该方法的新类的人强制使用结构。我能这样做吗?我开始认为这不是C ++提供的一种功能。

class XXX {
public:
    ///Should force any derived class to implement
    ///bool compute(const unsigned char i1, const unsigned char i2);
};

class GreaterThan : public XXX {
public:
    static inline bool compute(const unsigned char i1, const unsigned char i2) {
        return i1 > i2;
    }
};

class NotGreaterThan : public XXX {
public:
    static inline bool compute(const unsigned char i1, const unsigned char i2) {
        return i1 <= i2;
    }
};

class NotLessThan : public XXX { ///This should not compile
public:
    static inline bool compute2(const unsigned char i1, const unsigned char i2) {
        return i1 >= i2;
    }
};

[...]

在基类中定义纯虚方法compute不允许我在派生类中定义静态方法。让方法不是静态会迫使我在将它用作函子时实例化类,并且基本上会阻止内联。

注意:提出了类似的问题here

编辑:可能,这也不应该编译:

class LessThan : public XXX { ///Also this should not compile
public:
    static inline bool compute(const float i1, const float i2) {
        return i1 < i2;
    }
};

3 个答案:

答案 0 :(得分:2)

你想要的是静态多态性。

根本不需要继承。在您的示例中,这应该强制XXX的用户将bool compute(const unsigned char i1, const unsigned char i2);实现为静态方法:

template< typename C >
class XXX {
public:
    static void CallCompute(const unsigned char i1, const unsigned char i2)
    {
        const bool result = C::compute( i1, i2 );
        // use result somehow
    }
};

顺便说一下,请注意他们可以将compute()实现为bool compute(const T1 i1, const T2 i2);,其中T1和T2可以是任何整数或浮点类型。

答案 1 :(得分:1)

这几乎可以做你想要的:

#include <iostream>

template <typename Algorithm>
class UnsignedCharFunction {
    public:
    typedef Algorithm algorithm_type;
    static bool compute(const unsigned char i1, const unsigned char i2) {
        return call(algorithm_type::do_compute, i1, i2);
    }

    private:
    static bool call(
        bool (*f)(const unsigned char, const unsigned char),
        const unsigned char i1, const unsigned char i2) {
        return f(i1, i2);
    }
};

class GreaterThan : public UnsignedCharFunction<GreaterThan> {
    friend class UnsignedCharFunction<GreaterThan>;

    private:
    static bool do_compute(const unsigned char i1, const unsigned char i2) {
        return i1 > i2;
    }
};


class Invalid : public UnsignedCharFunction<Invalid> {
    friend class UnsignedCharFunction<Invalid>;

    private:
    #define N 2
    #if N == 1
    // Fails
    static bool no_do_compute(const unsigned char i1, const unsigned char i2) {
        return i1 >= i2;
    }
    #elif N == 2
    // Fails
    static bool do_compute(char i1, char i2) {
        return i1 >= i2;
    }
    #endif
};


int main() {
    std::cout << "A > B:" << GreaterThan::compute('A', 'B') << '\n'
              << "B > A:" << GreaterThan::compute('B', 'A') << '\n';
    // If you comment next line, there will be no error.
    Invalid::compute('A', 'B');
}

几乎是,由于模板的实例化,只有在使用函数时才会显示编译器错误。

关于内联:

volatile bool value; 
int main() {
    value = GreaterThan::compute('A', 'B');
}

00000000004005a0 <main>:
  4005a0: movb   $0x0,0x200aa5(%rip)        # 60104c <value>
  4005a7: xor    %eax,%eax
  4005a9: retq   
  4005aa: nopw   0x0(%rax,%rax,1)

在这个简单的小程序中代码将完全省略。

另一个内联:

volatile bool value;
volatile unsigned char a;
volatile unsigned char b;
int main() {
    value = GreaterThan::compute(a, b);
}

00000000004005a0 <main>:
  4005a0: movzbl 0x200aa5(%rip),%edx        # 60104c <b>
  4005a7: movzbl 0x200a9f(%rip),%eax        # 60104d <a>
  4005ae: cmp    %al,%dl
  4005b0: setb   %al
  4005b3: mov    %al,0x200a95(%rip)        # 60104e <value>
  4005b9: xor    %eax,%eax
  4005bb: retq   
  4005bc: nopl   0x0(%rax)

两者都编译为“g ++ -std = c ++ 11 -O3 -g”

答案 2 :(得分:0)

基类对其派生类一无所知,所以 没有真正的方法可以断言任何东西。在许多情况下, 你可以通过使基类成为模板来解决这个问题 它将派生类作为参数。那不行 但是,在这里,因为您需要进行静态检查 派生时立即出现编译时错误,并且在那时 那一刻,派生类不是一个完整的类型,你不能 使用其中的任何功能(即使在sizeof中也是如此 表达)。