C++模板和隐式类型转换

4

I have the following code:

#include <iostream>
#include "boost/shared_ptr.hpp"

using boost::shared_ptr;

class Base {
 public:
  virtual ~Base() {}
  virtual void print() = 0;
};

template <typename T>
class Child : public Base {
 public:
  virtual void print() {
    std::cout << "in Child" << std::endl;
  }
};

class GrandChild : public Child<int> {
 public:
  virtual void print() {
    std::cout << "in GrandChild" << std::endl;
  }
};

template <typename T>
void call_print(shared_ptr<Child<T> > a) {
  a->print();
}

void call_base_print(shared_ptr<Base> a) {
  a->print();
}

int main() {
  shared_ptr<GrandChild> gchild(new GrandChild);
  call_print(shared_ptr<Child<int> >(gchild));
  // call_print(gchild);  // Cannot compile!
  call_base_print(gchild);  // This works.
  return 0;
}

我发现很奇怪,call_base_print(gchild)可以正常工作,但call_print(gchild)会导致编译错误。我知道C ++不允许两个隐式转换,但我不认为这里有两个转换... 有人能解释一下吗?

1
虽然MSalters正确指出这是一个实例化问题而不是转换问题,但我认为值得指出的是,在模板推导中使用的参数没有允许任何隐式转换,有关详细信息,请参见我的答案https://dev59.com/FHNA5IYBdhLWcg3wrf83#868398#868398 - Pieter
2个回答

5

在类型转换之前,模板实例化就会失败。

call_base_print 不需要类型推导。 call_print<T>(shared_ptr<Child<T> > a) 需要。你正在传递一个 shared_ptr<GrandChild>。而且没有 T 可以替换,使得 shared_ptr<Child<T> >shared_ptr<GrandChild>。因此,实例化失败,没有可调用的函数。


0

你期望 shared_ptr<GrandChild> 是从 shared_ptr<Child> 派生而来的,只有这样才能进行隐式转换。但实际上它们是不同的类型。因此,call_print 期望的参数类型与你提供的不同。

另一个警告:即使从子类到超类有转换,由于你通过值传递参数,会导致子类对象被切片。

你可以通过使用指针参数而不是 shared_ptr 来获得你想要的行为。


实际上,即使使用愚蠢的指针也无法获得所需的行为,因为您将在Child<T>*参数和GrandChild*实际参数上执行模板参数推导。这仍然无法推断T。 - MSalters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接