我想在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等类型来不同地处理向量的元素。
答案 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;
}