繁体   English   中英

static 转换为向量后如何计算子类

[英]how to cout a subclass after static cast into a vector

我有两个类, Article和一个子类ArticleOnSale (公共继承)。

还有一个 class Boutique ,其中包含一个vector<Article*> arts Arts 。

我已经为ArticleArticleOnSale定义了<<运算符

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM