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

时间:2016-08-05 18:58:49

标签: c++ templates inheritance

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

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();
         }
     }
};

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

2 个答案:

答案 0 :(得分:1)

您可以使用中间函数和一些 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.
}

答案 1 :(得分:0)

你要问的是:

如何使用静态类型 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 :: type_info对象(1.8)(即动态   glvalue引用的类型。 [...]。

因此,我们通过向Base函数添加virtual来创建typeid多态类类型,然后我们应用to_close_thread,然后返回动态类型。