子类调用意外的重载函数

时间:2019-03-25 11:12:54

标签: c++ templates inheritance overloading template-meta-programming

我正在努力理解为什么在下面的代码中调用所谓的错误重载。

// overload.h
 struct T1
    {
      template<class... Args>
      void doFoo(Args&&... args)
        {
        std::cout << "T1 doFoo generic"<< std::endl;
        }

      void doFoo(int a)
        {
        std::cout << "T1 doFoo INT "<< std::endl;
        }

      void doFoo(double a)
        {
        std::cout << "T1 doFoo Double "<< std::endl;
        }

      template<class... Args>
      void foo(Args&&... args)
        {
        doFoo(args...);
        }
    };


  struct T2 : public T1
    {
      void doFoo(char c)
        {
        std::cout << "T2 doFoo char " << std::endl;
        }
    };

  // main.cpp

  #include <overload.h>
  int main()
    {
    T2 t2;
    t2.foo(3);
    t2.foo('A'); // This outputs: T1 doFoo generic 
    }

我期望t2.foo('A')的输出为:“ T2 doFoo char”,但我却得到了“ T1 doFoogeneric”。

如果我将T2 :: doFoo(char c)移至T1,则一切正常。这种行为的原因是什么?任何解决方法?

1 个答案:

答案 0 :(得分:1)

正如注释中已经建议的那样,由于T1不知道派生的结构T2,因此T1::foo也找不到T2::doFoo(char c),并且此静态绑定无法找到实现。

T1::foo中的char虚假重载T2的一种简单变通办法是再次在foo中声明T2并按如下方式重载:

DEMO

struct T1 
{
    template<class... Args>
    void doFoo(Args&&... args){
        std::cout << "T1 doFoo generic"<< std::endl;
    }

    void doFoo(int a){
        std::cout << "T1 doFoo INT "<< std::endl;    
    }

    void doFoo(double a){
        std::cout << "T1 doFoo Double "<< std::endl;
    }

    template<class... Args>
    void foo(Args&&... args){
        doFoo(std::forward<Args>(args)...);
    }
};

struct T2 : public T1
{
    template<class... Args>
    void foo(Args&&... args){
        T1::foo(std::forward<Args>(args)...);
    }

    void foo(char c){
        std::cout << "T2 foo char " << std::endl;
    }
};