从基指针向下转换到模板化派生类型
Downcasting from base pointer to templated derived types
我有以下层次结构:
class base
{
public:
virtual ~base(){}
virtual void foo() {}
};
template <typename T>
class derived1 : public base
{
virtual void foo() {};
};
template <typename T>
class derived2 : public base
{
virtual void foo() {};
};
现在给一个指向基地的指针,我想知道底层是derived1或derived2。问题是derived1和derived2可以专门用于许多不同的类型,使用dynamic_cast测试向下转换需要要知道的模板类型。我最终得到了混乱、无法维护和不完整的代码:
base* b = new derived1<int>();
if (dynamic_cast<derived1<int>*> ||
dynamic_cast<derived1<unsigned int>*> ||
dynamic_cast<derived1<double>*>)
std::cout << "is derived1";
else if (dynamic_cast<derived2<int>*> ||
dynamic_cast<derived2<unsigned int>*> ||
dynamic_cast<derived2<double>*>)
std::cout << "is derived2";
有没有更好的方法,可以处理任何类型的专业化?
将依赖于类型的逻辑移动到类型中。
代替:
if (dynamic_cast<derived1<int>*>(b) ||
dynamic_cast<derived1<unsigned int>*>(b) ||
dynamic_cast<derived1<double>*>(b))
std::cout << "is derived1";
else if (dynamic_cast<derived2<int>*>(b) ||
dynamic_cast<derived2<unsigned int>*>(b) ||
dynamic_cast<derived2<double>*>(b))
std::cout << "is derived2";
将virtual print_name() const
函数添加到base
,然后执行:
void example() {
std::unique_ptr<base> b(new derived1<int>());
b->print_name();
}
class base
{
public:
~base(){}
virtual void foo() {}
virtual void print_name() const = 0;
};
template <typename T>
class derived1 : public base
{
virtual void foo() {}
virtual void print_name() const {
std::cout << "is derived1";
}
};
template <typename T>
class derived2 : public base
{
virtual void foo() {}
virtual void print_name() const {
std::cout << "is derived2";
}
};
在base
和derived1
或derived2
:之间插入一个非模板类
class base
{
public:
virtual ~base() {} // **NOTE** Should be virtual
virtual void foo() {}
};
class derived1_base : public base
{
};
template <typename T>
class derived1 : public derived1_base
{
public:
virtual void foo() {}
};
class derived2_base : public base
{
};
template <typename T>
class derived2 : public derived2_base
{
public:
virtual void foo() {}
};
在一条评论中,你提到:
[我想]为每个函数调用一个特定的函数-顺便说一句derived1和derived2
将该(虚拟)函数添加到derived1_base
中,您甚至不需要再了解T
。
if (dynamic_cast<derived1_base*>(foo))
{
std::cout << "is derived1";
dynamic_cast<derived1_base*>(foo)->specific_derived1_function();
}
else if (dynamic_cast<derived2_base*>(foo))
{
std::cout << "is derived2";
dynamic_cast<derived2_base*>(foo)->specific_derived2_function();
}
注意:我认为dynamic_cast<>
是一个代码气味的列表,我敦促您重新思考您的方法。
您可以添加一个虚拟方法来进行某种类型的元类型检查:
class base
{
public:
~base(){}
virtual void foo() {}
virtual bool isa(const char* type_to_test){
return strcmp(type_to_test,"base")==0;}
};
template <typename T>
class derived1 : public base
{
virtual void foo() {};
virtual bool isa(const char* type_to_test){
return strcmp(type_to_test,"derived1")==0;}
};
解决方案1:再添加一个虚拟函数:
enum DerivedType
{
One,
Two,
...
};
class base
{
public:
~base(){}
virtual void foo() {}
virtual DerivedType GetType() = 0;
};
template <typename T>
class derived1 : public base
{
virtual void foo() {};
virtual DerivedType GetType() { return One; }
};
template <typename T>
class derived2 : public base
{
virtual void foo() {};
virtual DerivedType GetType() { return Two; }
};
解决方案2:使用标签类:
class Base
{
public:
virtual ~Base() { }
};
class Derived1Tag
{ };
class Derived2Tag
{ };
template <class T>
class Derived1 : public Base, public Derived1Tag
{ };
template <class T>
class Derived2 : public Base, public Derived2Tag
{ };
int main(int argc, char** argv)
{
Derived1<int> d1;
Derived2<int> d2;
cout << dynamic_cast<Derived1Tag*>((Base*)&d1) << endl;
cout << dynamic_cast<Derived1Tag*>((Base*)&d2) << endl;
return 0;
}
相关文章:
- 在 C++ 中用派生类型重写成员函数
- 在 C++ 中将对象转换为派生类型
- C++如果采用类类型的函数被传递派生类型,有没有办法给出错误?
- 返回派生类型时出现协变类型错误
- 如何模板化堆栈分配的多态指针数组到接口,包括派生类型的相应点?
- 基于派生类型的编译时行为分支
- 按类型排序向量并按类型或派生类型搜索
- 为什么"运算符<<"不适用于指向派生类型的成员?
- 无法返回派生类型的标准::unique_ptr<>
- 无法从派生类型的作用域访问另一个实例的受保护成员
- dynamic_cast到具有未知模板参数的派生类型
- 派生类型的成员
- 视觉C++ dynamic_cast返回 NULL,尽管对象是派生类型
- 在运算符中动态强制转换为派生类型<<
- 如何在不转换回基类类型的情况下返回派生类型的对象?
- 将派生指针分配给C 中的其他派生类型
- 如何将派生类型的对象放在用于基本类型的向量中
- C++ - 无法将派生类型作为基类型列表传递给构造函数
- 如何在基本类型参考中存储对派生类型的参考
- 统一处理具有协变类型的函数指针(如何使用派生类型调用回调?