【问题标题】:Fail to compile non-overloaded function in template argument无法编译模板参数中的非重载函数
【发布时间】:2015-07-16 20:24:48
【问题描述】:

我有这四个类:

class  BaseWrapper {
public:
  virtual void Process(int i) = 0;
};

template<typename T>
class Wrapper : public BaseWrapper {
public :
  Wrapper(T * arg): var(arg) {}
  void Process(int i) {
     this->var->Process(i);
  }
private:
  T * var;
};

class Base {
public :
  void Process(int) {}
};

class Derived : public Base {
public:
  Derived() {
    BaseWrapper * wrap = new Wrapper<Derived>(this);
  }
  void       Process(std::string) {}
};

所以基本上Derived类并没有重载Process方法,而这个方法是包装器需要的。当我编译这个时,我得到'没有匹配函数调用 Derived::Process(int)'。

难道 Process 方法还不能定义在 Derived 类中吗?我也尝试在 Base virtual 中声明 Process 方法,它没有改变任何东西。

我不是在寻找解决方法(我通过重载 Process 方法并在其中调用父方法找到了解决方法),但我试图理解为什么它不能编译。

[编辑]:如果我从 Derived 中删除 'void Process(std::string)',它会编译。因此,问题似乎来自存在同名的不同方法。

【问题讨论】:

    标签: c++ templates overloading derived-class


    【解决方案1】:

    如果你改变这个:

    void  Process(std::string) {}
    

    到这里:

    void  Process(int) {}
    

    您的代码将编译。这是关于为什么我的代码无法编译的strong提示。


    让我们看看这里发生了什么:

    我们有:

    Derived() {
      BaseWrapper * wrap = new Wrapper<Derived>(this);
    }
    

    它将调用Wrapper 的构造函数,并将Wrapper 类的数据成员分配给Derived 类(数据成员是一个指针,但这不是什么大问题)。

    现在,在 Wrapper 类中,我们有:

    void Process(int i) {
      this->var->Process(i);
    }
    

    这是问题所在。你看,在这个函数的主体中,我们说取Wrapper的数据成员,它指向类Derived,然后调用我们指向的类的Process()!那是 Derived 类,它有 void Process(std::string),因此我们公平地收到了这个错误:

    error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
          this->var->Process(i);
    

    这与您收到的错误类似。

    希望这会有所帮助! //+1 是我今天的一个很好的入门问题 :)


    如果你不想重载函数,那么帮助编译器说它应该检查从基类继承的方法,而不是Derived类中定义的方法,这应该是第一个选择编译器。

    那么你的代码应该是这样的:

    class Base; // forward declaration, or just define Base class here
    
    template<typename T>
    class Wrapper : public BaseWrapper {
    public :
      Wrapper(T * arg): var(arg) {}
      void Process(int i) {
         this->var->Base::Process(i); // Say that you want the Process() of Base
      }
    private:
      T * var;
    };
    

    【讨论】:

    • 问题是该方法的 Process(int) 版本已经在 Base 类中定义,我不希望重载它。但是既然它是在基类中定义的,它不应该在派生类中定义吗?这是我问自己的问题。 Process(std::string) 版本只是包装器不会使用的另一种方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多