我瞭解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