[英]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.