对特殊情况行为使用继承或模板

Using inheritance or templates for special case behavior

本文关键字:继承 情况      更新时间:2023-10-16

我有两个类AB,它们是具有operate()方法的Operator类的子类。

class Operator {
     // ...
     virtual void operate() = 0;
};
class A : public Operator {
     void operate() { /* ... */ }
};
class B : public Operator {
     void operate() { /* ... */ }
};

我想创建一个执行两个操作的类,但当两个操作都是B类型时,它具有唯一的行为。类似的东西

 class DoubleOperator {
     Operator* operator1;
     Operator* operator2;
     // ...
 public:
     void operateTwice() {
         if (/* operator1 and operator2 are of type B */) {
             // Do a special combined operation.
         } else { // Otherwise, do the operations separately.
             operator1->operate();
             operator2->operate();
         }
     }
};

有没有一种简单的方法可以使用继承或模板来产生这种行为?

您可以键入带有中间函数和一位SFINAE的擦除运算符
它遵循一个最小的工作示例(C++14,很容易转换为C++11(:

#include<type_traits>
#include<iostream>
class Operator {
     // ...
     virtual void operate() = 0;
};
class A : public Operator {
     void operate() { /* ... */ }
};
class B : public Operator {
     void operate() { /* ... */ }
};
class DoubleOperator {
    template<typename T, typename U>
    static
    std::enable_if_t<std::is_same<T,U>::value>
    proto() {
        std::cout << "same" << std::endl;
        // Do a special combined operation.
    }
    template<typename T, typename U>
    static
    std::enable_if_t<not std::is_same<T,U>::value>
    proto() {
        std::cout << "not same" << std::endl;
        // Otherwise, do the operations separately.
    }
     Operator* operator1;
     Operator* operator2;
     void(*internalOperatorTwice)(void);
     // ...
public:
    template<typename T, typename U>
    DoubleOperator(T *t, U *u): operator1{t}, operator2{u} {
        internalOperatorTwice = &proto<T, U>;
    }
     void operateTwice() {
         internalOperatorTwice();
     }
};
int main() {
    A a1;
    A a2;
    B b;
    DoubleOperator do1{&a1, &a2};
    do1.operateTwice();
    DoubleOperator do2{&a1, &b};
    do2.operateTwice();
}

您可以根据需要相应地扩展/修改proto

编辑

我又读了一遍这个问题,下面是对答案的提炼
我上面说的仍然有效。无论如何,如果您只想在有两个B实例时执行不同的操作,则可以使用以下proto函数:

template<typename T, typename U>
static
std::enable_if_t<std::is_same<T,B>::value and std::is_same<U,B>::value>
proto() {
    std::cout << "same" << std::endl;
    // Do a special combined operation.
}
template<typename T, typename U>
static
std::enable_if_t<not (std::is_same<T,B>::value and std::is_same<U,B>::value)>
proto() {
    std::cout << "not same" << std::endl;
    // Otherwise, do the operations separately.
}

你要问的是:

如何检查Derived是否为静态类型Base&的变量的动态类型

struct Base
{
    virtual void f(){}
};
struct Derived:Base{};
Derived d;
Base& b = d;
if (typeid(b)==typeid(Derived))
{
    //...
}

说明:

5.2.8/2说:

当typeid应用于类型为多态类类型(10.3(的glvalue表达式时,结果引用到一个std::typeinfo对象,该对象表示最派生对象(1.8(的类型(即动态类型(。[…].

因此,我们通过添加virtual函数来生成Base多态类类型,并应用typeid,然后返回动态类型。