我了解C++类的多态性的方式,它允许以相同的方式处理类及其子类。因此,如果我有一个类及其子类的多个对象,并将它们存储在基类的(智能)指针向量中,则可以调用它们上的任何虚拟方法,它将工作得很好。如何在处理基类的多重指针时同时处理多态性?
class Dancer {
public:
virtual void f() const { std::cout << "I am a basic dancer" << std::endl; }
};
class SkilledDancer : public Dancer {
public:
void f() const { std::cout << "I am a skilled dancer" << std::endl; }
};
int main(int argc, char *argv[])
{
std::vector< std::shared_ptr<Dancer> > dancers;
dancers.push_back(std::make_shared<Dancer>(Dancer()));
dancers.push_back(std::dynamic_pointer_cast<Dancer>(std::make_shared<SkilledDancer>(SkilledDancer())));
for(auto & dancer : dancers){
dancer->f(); //works fine
}
}
但现在我有一个问题,当我想这种行为,使用运营商或与两个对象处理方法时。如果一个函数需要输入基类的两个参数,我该如何考虑它们实际上可能是派生类的对象的事实?
class Dancer {
public:
virtual void g(const Dancer & d) const { std::cout << "Let's do a basic dance" << std::endl; }
};
class SkilledDancer : public Dancer {
public:
//what should I do here ?
void g(const Dancer & d) const { std::cout << "Let's do an advanced dance" << std::endl; }
//would overload Dancer::g but wrong because d is only a Dancer
void g(const SkilledDancer & d) { std::cout << "Let's do an advanced dance" << std::endl; }
//doest not overload Dancer::g because different signature
//so would never be called if dealing with two smart pointers of the base class
};
int main(int argc, char *argv[])
{
auto basic = std::make_shared<Dancer>(Dancer());
auto advanced = std::dynamic_pointer_cast<Dancer>(std::make_shared<SkilledDancer>(SkilledDancer()));
basic->g(*advanced); //OK
advanced->g(*advanced); //seems good ...
advanced->g(*basic); //... but wrong
}
我设法找到一个解决方法(下面的代码),但它需要派生类的一个其他成员,另外两个函数调用,该函数不能是const了。所以我想知道是否有更好的方法来处理这个问题。
如果我面临XY问题,我的实际问题是关于矩阵。我希望有一个矩阵算子乘以矩阵,但是当处理两个特定的矩阵(如三角形或对称矩阵类的子类)时,我想调用另一个算子。请注意,所有类型的矩阵都存储为矩阵基类的指针。
class Dancer {
public:
virtual void g(const std::shared_ptr<Dancer> & d) { std::cout << "Let's do a basic dance" << std::endl; }
};
class SkilledDancer : public Dancer {
public:
SkilledDancer() : dummy_g(false) {}
bool dummy_g;
void g(const std::shared_ptr<Dancer> & d) {
if(!dummy_g){
dummy_g = true;
d->g(std::dynamic_pointer_cast<Dancer>(std::make_shared<SkilledDancer>(*this)));
} else {
dummy_g = false;
((SkilledDancer*)d.get())->dummy_g = false;
std::cout << "Let's do an advanced dance" << std::endl;
}
}
};
int main(int argc, char *argv[])
{
//all cases work fine
basic->g(basic);
advanced->g(advanced);
basic->g(advanced);
advanced->g(basic);
}
查找双倍/多次调度。 –
[OT]:您应该从'std :: make_shared(Dancer())'' –
Jarod42
'中移除'Dancer()'谢谢你告诉我背后的概念的名字。因此,如果我理解正确,那么在C++中就不存在对多次调度的本地支持(维基百科文章提到访客模式的动态转换,但它们似乎不是很好的选择)。 好评的make_shared评论! – yultan