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

时间:2009-09-02 10:24:41

标签: c++

我有以下代码:

#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 ++不允许两次隐式转换,但我不认为这里有两次转换......有人可以启发我吗?

2 个答案:

答案 0 :(得分:5)

你没有达到类型转换的程度。它在模板实例化中更早失败。

call_base_print不需要类型扣除。 call_print<T>(shared_ptr<Child<T> > a)。你传递的是shared_ptr<GrandChild>。并且根本没有T可以代替,shared_ptr<Child<T> >shared_ptr<GrandChild>。因此,实例化失败,并且没有调用函数。

答案 1 :(得分:0)

您希望shared_ptr<GrandChild>派生自shared_ptr<Child>,然后才能进行隐式转换。它不是;这是一个不同的类型。所以call_print期待的是另一种类型的参数而不是你提供的。

另一个警告:即使从子类转换到超类,也会导致子类对象的切片,因为你按值提供参数。

您可以使用指针参数i.s.o来获取您的目标行为。 shared_ptr秒。