如何将Base *指针视为Derived <t> * pointer?</t>

时间:2010-04-17 22:18:42

标签: c++ templates types

我想在Base中存储指向vector类的指针,但是然后将它们用作函数参数,它们充当特定的类,请参见此处:

#include <iostream>
#include <vector>

class Base {};

template<class T>
class Derived : public Base {};

void Foo(Derived<int>* d) {
  std::cerr << "Processing int" << std::endl;
}

void Foo(Derived<double>* d) {
  std::cerr << "Processing double" << std::endl;
}

int main() {
  std::vector<Base*> vec;
  vec.push_back(new Derived<int>());
  vec.push_back(new Derived<double>());
  Foo(vec[0]);
  Foo(vec[1]);
  delete vec[0];
  delete vec[1];
  return 0;
}

这不编译:

error: call of overloaded 'Foo(Base*&)' is ambiguous

是否有可能使其有效?我需要根据int,double等类型来不同地处理向量的元素。

4 个答案:

答案 0 :(得分:5)

你需要使用方法多态,因为它是动态的,而不是函数重载,这是静态的(编译时)。要在模板化类型上重载,您需要使用模板特化。

示例:

#include <iostream>
#include <vector>

class Base {
  public:
    virtual void Foo() {
      std::cerr << "Processing base" << std::endl;
    }
};

template<class T>
class Derived : public Base {};

template <>
class Derived <int> : public Base {
  public:
    void Foo() {
      std::cerr << "Processing int" << std::endl;
    }
};

template <>
class Derived <double> : public Base {
  public:
    void Foo() {
      std::cerr << "Processing double" << std::endl;
    }
};

int main() {
  std::vector<Base*> vec;
  vec.push_back(new Derived<int>());
  vec.push_back(new Derived<double>());
  vec[0]->Foo();
  vec[1]->Foo();
  delete vec[0];
  delete vec[1];
  return 0;
}

答案 1 :(得分:1)

当您从Derived<int>*进行类型转换为Base*时,除非使用RTTI(运行时类型识别),否则将丢失有关您拥有的派生类的信息。

如果您已启用RTTI,则可以尝试使用Base*dynamic_cast<>()转发类型转发为派生类型指针:

void Foo(Base* base)
{
    Derived<int>* derivedInt = dynamic_cast<Derived<int>*>(base);
    if(derivedInt)
    {
        Foo(derivedInt);
        return;
    }
    Derived<double>* derivedDouble = dynamic_cast<Derived<double>*>(base);
    if(derivedDouble)
    {
        Foo(derivedDouble);
        return;
    }
    // Handle other cases here.
}
如果指针未指向正确的类型,

dynamic_cast将返回NULL。

或者,如果您不想使用RTTI和dynamic_cast,则必须保留一些方法来确定向量中存储哪个子类(通常与指针一起存储的enum值,可能在pair中,或在Base中使用返回类似enum的方法,并使用reinterpret_cast<>()对指针进行类型转换。

答案 2 :(得分:1)

当然它是模棱两可的,编译器如何在vec [0]中找出Base的哪个特定子类。

您可以通过明确的演员来解决歧义:

Foo( (Derived<int>*) vec[0] )

或者,更好的是,考虑使用动态方法解析:

class Base {
    virtual void Foo() = 0;
};

template <class T>
class Derived: Base {
    void Foo() { /* .. doFoo<T>(...) .. */ }
};

template<class T> void doFoo() { /* .. general case .. */ }
template<> void doFoo<int>() { /* .. int case .. */}
template<> void doFoo<double>() { /* .. double case .. */}

并在您的代码中调用

vec[0]->Foo()

答案 3 :(得分:1)

你可以这样做:

#include <iostream>
#include <vector>

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

template<class T>
class Derived : public Base {
public:
  virtual void DoFoo() {
          Foo(this);
  }
};

void Foo(Derived<int>* d) {
  std::cerr << "Processing int" << std::endl;
}

void Foo(Derived<double>* d) {
  std::cerr << "Processing double" << std::endl;
}


int main()
{
  std::vector<Base*> vec;
  vec.push_back(new Derived<int>());
  vec.push_back(new Derived<double>());
  vec[0]->DoFoo();
  vec[1]->DoFoo();
  delete vec[0];
  delete vec[1];

  return 0;
}