簡體   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