[英]how to cout a subclass after static cast into a vector
我有兩個類, Article
和一個子類ArticleOnSale
(公共繼承)。
還有一個 class Boutique
,其中包含一個vector<Article*> arts
Arts 。
我已經為Article
和ArticleOnSale
定義了<<
運算符
在Articles.cpp
我有一個公共的Addarticle
void Addarticle(Article* a)
{
Article* p;
if (typeid(*a) == typeid(Article))
{
p = new Article(a);
arts.push_back(p);
cout << "\narticle\n";
}
else
{
p = new ArticleEnSolde(static_cast<const ArticleEnSolde&>(*arts[arts.size()])); //creates a huge problem
arts.push_back(p);
}
}
當我想打印Article
Article
ArticleOnSale
的<<
。
ostream & operator<<(ostream& n, Boutique a)
{
n<<"\nshowing boutique:\n";
Article* p;
for (int i = 0; i < a.arts.size(); i++)
{
p = a.arts[i];
if (typeid(*a.arts[i]) == typeid(Article))
{
n << *a.arts[i];
n << "\narticle not on sale detected\n";
}
else
{
n << "i can detect article on sale";//just debugging (doesn't work)
}
}
return n;
}
更好地利用虛函數的可能實現是這樣的:
class Article {
public:
virtual bool is_on_sale() const { return false; }
};
class ArticleOnSale {
public:
virtual bool is_on_sale() const { return true; }
};
那么你的向量需要看起來像:
std::vector<std::unique_ptr<Article>> arts;
// add an Article:
arts.push_back(std::make_unique<Article>());
// or on sale
arts.push_back(std::make_unique<ArticleOnSale>());
(需要unique_ptr
以便 C++ 虛函數能夠運行,如果沒有它的指針,這將不起作用)。
最后,ostream 運算符變得相當簡潔:
ostream & operator<<(ostream& os,Boutique a ) {
for (auto& ptr : a.arts) {
os << (ptr->is_on_sale() ? "article on sale " : "article is full price ")
}
}
當然,可能有更好的方法,比如在Article
中存儲一個 boolean 變量(如果它正在銷售) - 但我希望這能讓代碼表現得更像你所期望的!
這段代碼有很多問題。
在Addarticle()
中, typeid(*a)
將始終等於typeid(Article)
。 檢查a
是否指向特定派生類型的 object 的正確方法是使用dynamic_cast
代替,例如:
if (dynamic_cast<ArticleEnSolde*>(a))
{
// a is an ArticleEnSolde ...
}
else
{
// a is not an ArticleEnSolde ...
}
此外,在static_cast<const ArticleEnSolde&>(*arts[arts.size()])
中,訪問arts[arts.size()]
超出了vector
的范圍。 您可能打算改用a
。
但是,在這種情況下,如果您不打算將a
本身按原樣推入vector
中,則應使用clone()
習慣用法:
class Article
{
public:
virtual Article* clone() const;
};
class ArticleEnSolde : public Article
{
public:
Article* clone() const override;
};
...
Article* Article::clone() const
{
return new Article(*this);
}
Article* ArticleEnSolde::clone() const
{
return new ArticleEnSolde(*this);
}
void Addarticle(Article* a)
{
Article* p = a->clone();
arts.push_back(p);
}
關於打印,您僅對Article
調用operator<<
,因為這是您傳遞給它的 object 的類型。 無法知道 object 是否真的是ArticleEnSolde
。 對於多態類型,您應該在基礎 class 中定義一個virtual
方法,然后為該 class 定義operator<<
並讓它調用虛擬方法:
class Article
{
public:
virtual void print(ostream &n) const;
};
class ArticleEnSolde : public Article
{
public:
void print(ostream &n) const override;
};
ostream& operator<<(ostream& n, const Article &a);
...
void Article::print(ostream &n) const
{
n << "\narticle not on sale\n";
}
void ArticleEnSolde::print(ostream &n) const
{
n << "\narticle on sale\n";
}
ostream& operator<<(ostream& n, const Article &a)
{
a.print(n);
return n;
}
ostream& operator<<(ostream& n, const Boutique &a)
{
n << "\nshowing boutique:\n";
for (size_t i = 0; i < a.arts.size(); ++i)
{
n << *(a.arts[i]);
}
return n;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.