tra*_*mot 3 c++ inheritance dynamic-cast vector static-cast
这是我的问题的后续内容: Updating data Members of different obliged Class of the same base class inside a vector
我正在 C++ 中构建一个 3D 网格模型,它具有不同的单元类型,所有单元类型都存储在Grid类中的向量中。我定义了一个GridCell基类,并且还有几个派生类GridCell1、GridCell2、GridCell3等。
我将GridCell对象传递到模型进程中。传递的GridCell对象类型(其派生类)将与接收模型进程一起使用。换句话说,模型进程模型进程被设计(可能是不正确的),具有不同的函数,期望对适当的派生对象的数据成员进行操作。当然,他们看不到,因为对象是从 中拉出的,std::vector<gridCell*> gridCellVector所以它只将该对象视为指向基类的指针。此时,我有两个选择:1)重写我的模型流程,2)使用static_cast或dynamic_cast向下转换传递的对象。
问题:在这种情况下,当我的模型进程(仅在正确类型的GridCell对象上运行)知道它们正在接收什么派生类时,我应该使用 static_cast 还是dynamic_cast?人们似乎真的不喜欢使用这些工具。为什么我应该远离使用这些?
有时强制转换是不可避免的,因为多态性并不能解决所有问题。然而,多态性实际上是为了消除了解类型的需要而设计的。如果您需要知道类型,那么您必须询问多态性是否是适合该工作的工具,或者您是否未能正确实现多态性。
理想的情况是每个对象都知道自己的行为,以便其他人if/else在处理通用类型时不需要做出决定。
为此,您通常会将处理代码放在类型本身内部,而不是使用需要if/else为收到的每个对象做出决策的外部处理例程。
因此,虽然铸造本质上并不是坏事,因为有时这是必要的,但如果您需要使用它,它也可能是设计不良的症状。
问题:在这种情况下,当我的模型进程(仅在正确类型的GridCell对象上运行)知道它们正在接收什么派生类时,我应该使用 static_cast 还是dynamic_cast?人们似乎真的不喜欢使用这些工具。为什么我应该远离使用这些?
如果您确实知道类型,则使用static_cast(它更快),否则使用dynamic_cast.
铸造的替代方案:
您可以使用的一种“技巧”(有效的转换)是使用多态性来为您选择正确的类型。
您可以做的就是向基类添加一个虚函数GridCell,该函数获取单独处理子类型的类的对象,并让重写的子类型自行调用相关的处理函数。这样,类型本质上就知道需要如何处理它。
一个例子
class Processor
{
public:
void process_1(class GridCell1* cell)
{
std::cout << "processing type 1\n";
}
void process_2(class GridCell2* cell)
{
std::cout << "processing type 2\n";
}
};
class GridCell
{
public:
virtual ~GridCell() {}
virtual void process(Processor& proc) = 0;
};
class GridCell1
: public GridCell
{
public:
void process(Processor& proc) override
{
proc.process_1(this);
}
};
class GridCell2
: public GridCell
{
public:
void process(Processor& proc) override
{
proc.process_2(this);
}
};
class Grid
{
std::vector<GridCell*> gridCellVector;
public:
Grid()
{
gridCellVector.push_back(new GridCell1);
gridCellVector.push_back(new GridCell1);
gridCellVector.push_back(new GridCell2);
gridCellVector.push_back(new GridCell1);
gridCellVector.push_back(new GridCell2);
gridCellVector.push_back(new GridCell1);
}
~Grid() { for(auto cell: gridCellVector) delete cell; }
void process()
{
Processor proc;
for(auto cell: gridCellVector)
cell->process(proc);
}
};
int main ()
{
Grid grid;
grid.process();
}
Run Code Online (Sandbox Code Playgroud)
输出:
processing type 1
processing type 1
processing type 2
processing type 1
processing type 2
processing type 1
Run Code Online (Sandbox Code Playgroud)