基类中运算符重载的问题

时间:2014-05-09 16:23:02

标签: c++ inheritance operator-overloading

嗨我在安装和操作员超载方面遇到了一些麻烦,我希望你们能给我一些清晰度。

我有以下课程:

template<typename Type>
class Predicate{
public:
    Predicate() {};
    virtual ~Predicate(){};
    virtual bool operator()(const Type & value) = 0;
    virtual bool operator()(const Type * value){ //<-- this is the operator thats not working
        return (*this)(*value);
    };
};

template<typename Type>
class Always : public Predicate<Type>{
public:
    bool operator()(const Type & value){return true;}
    ~Always(){};
};

现在我希望我的所有谓词都接受引用和指针,但是当我测试这些类时:

int main(){
    Always<int> a;
    int i = 1000;
    a(&i);
    system("pause");
    return 1;
}

我收到以下错误:

test.cpp: In function 'int main()':
test.cpp:10:6: error: invalid conversion from 'int*' to 'int' [-fpermissive]
  a(&i);
      ^
In file included from test.cpp:2:0:
predicates.h:22:7: error:   initializing argument 1 of 'bool Always<Type>::operator()(const Type&) [with Type = int]' [-fpermissive]
  bool operator()(const Type & value){return true;}

2 个答案:

答案 0 :(得分:2)

这是因为当你宣布:

bool operator()(const Type & value){return true;}

在子类中,您隐藏 / shadowing 超类中运算符的任何其他重载。

如果你添加:

using Predicate<Type>::operator();

Live demo

在子类中,一切都会正常工作。


另一方面,我认为同时允许const&const*都是一种设计气味。您应该只允许const&版本,如果他们的指针有*ptr,那么让您的班级用户ptr

答案 1 :(得分:0)

模板和运算符重载在这里模糊了真正的问题。看看这段产生相同错误的小代码:

void f(int &);

int main()
{
  int *ptr;
  f(ptr);
}

编译器不允许传递指向预期引用的指针。这是您尝试使用派生类进行的操作。当您使用具体的Always时,不会考虑operator()的基本版本。

当你操作基类的指针(或引用)时,看看情况如何变化:

int main(){
    Predicate<int> *ptr = new Always<int>;
    int i = 1000;
    (*ptr)(&i);
    delete ptr;
}

这编译很好,因为基类运算符现在被认为是重载解析。但这只是为了让您更好地理解问题。 解决方案将应用Non-Virtual Interface Idiom。使您的运营商非虚拟化,并在私有虚拟功能方面实施:

template<typename Type>
class Predicate{
public:
    Predicate() {};
    virtual ~Predicate(){};
    bool operator()(const Type & value) { return operatorImpl(value); }
    bool operator()(const Type * value) { return operatorImpl(value); }

private:
    virtual bool operatorImpl(const Type & value) = 0;
    virtual bool operatorImpl(const Type * value) {
        return (*this)(*value);
    }
};

template<typename Type>
class Always : public Predicate<Type>{
public:
    ~Always(){};
private:
    bool operatorImpl(const Type & value){return true;}
};