模板 class 实现存在编译问题

Template class implementation has compilation issues

我正在使用 class 的静态成员函数创建一个对象。然后在里面调用一个函数。

int main(){
  int a = 49;
  auto foo = Foo::createFoo(a);

  foo->study();
}

实施
对于此示例,让 study() 显示一个值。
在结构方面,我确实有限制,必须有下面的接口,然后是返回对象的静态方法

class I_Foo{
public:
  virtual void study(void) = 0;
};

class Foo : public I_Foo{
public:
  static Foo* createFoo(int x_) {
    return new Foo(x_);
  }
  
  void study() override{
    std::cout << "studied: "<< st << std::endl;
  }

protected:
  Foo(int a) : st(a) {}

  int st = 0;
};

上述实现绝对有效,正如预期的那样即变量 a 应显示为 studied: a

现在我想改变这个
的行为 假设对于低于 50 的值,上述实现应保持 “不变” ,即变量 a 应显示为 studied: a
但是,当值变为 50 及以上时,输出应显示 studied: a+100


#include <iostream>

class I_Foo{
public:
  virtual void study(void) = 0;
};

template<int>
class FooImpl;

class Foo : public I_Foo {
public:
  static Foo* createFoo(int x_) {
    
    Foo* foo = nullptr;
    if (x_>=50) {
        foo = new FooImpl<2>(x_);
    }
    else {
        foo = new FooImpl<1>(x_);
    }
    return foo;
  }
};

template<int FT = 1>
class FooImpl : public Foo{
public:

  void study() override{
    std::cout << "studied: "<< st << std::endl;
  }

  FooImpl(int a) : st(a) {}

  int st = 0;
};

template<>
void FooImpl<2>::study() override{
  std::cout << "studied: "<< st + 100 << std::endl;
}

int main()
{
  int a = 56;
  auto foo = Foo::createFoo(a);

  foo->study();
}

这显然无法编译,因为 Foo 不知道 FooImpl 是什么!

请建议我如何才能完成这项工作。要求是保持主要功能不变,但具有新功能。

请注意 是的,我知道这可以通过 if 语句解决,但这不是重点。它在现实中有一个复杂的实现,我只是试图将它呈现在一个相当容易理解的问题中,以研究这些模板如何工作。

编辑 1
第一次编辑后,我看到以下编译错误

正如我在评论中所写:不要在 class 声明中实现 createFoo 函数。

#include <iostream>

class I_Foo {
public:
  virtual void study(void) = 0;
};

class Foo : public I_Foo {
public:
  // here just DECLARE the method...
  static Foo *createFoo(int x_);
};

/********/
/* SNIP */
/********/

// ...and IMPLEMENT it there
Foo *Foo::createFoo(int x_) {
    if (x_>=50) { 
      return new FooImpl<2>(x_);
    } else {
      return new FooImpl<1>(x_);
    }
}

int main() {
  int a = 56;
  auto foo = Foo::createFoo(a);

  foo->study();
}