C++ 类方法在其他方法之前运行

标签 c++

关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。












想改进这个问题?将问题更新为 on-topic对于堆栈溢出。

8年前关闭。




Improve this question




我过去曾多次使用过这个网站,以前从未真正发布过问题,但我不知道如何简单地说出这个问题。我在 Devry 的 C++ 课上,我项目的实际作业要求方面已经完成,但我正在添加一些练习元素。

因此,为了完成家庭作业,我添加了一个名为 Song 的额外类(class)。它有 2 个私有(private)变量(标题和长度),一些基本的构造函数和 = 和 == 的操作重载。这一切都很好。然后我将 Song 类的数组添加到 Cd 类(每个 Cd 的最大歌曲数为 10)。我为 Cd 创建了一些新方法:

  • addSong(歌曲);
  • removeSong(歌曲);
  • 组织歌曲();和
  • 修改 Report() 常量;

  • 根据选择的数量按顺序写出歌曲。选择和播放时间的 Cd 私有(private)值现在分别与歌曲总数和这些歌曲的总长度相关联。一切正常。 removeSong 从列表中取出指定的歌曲,然后调用organizeSong 将剩余的歌曲设置为数组中的最低值。但是,无论我在哪里调用 removeSong(Song s) 似乎都会在任何东西写入程序之前将其删除。
    因此下面的代码将从 Cd 中提取信息,但尽管在 Report 方法之后调用了 removeSong 方法,但只提取了一首歌曲。有人知道为什么吗?
    Song s1("Hey Jude", 4.52);
    Song s2("The song of Pie", 3.14);
    
    Cd c1 ("Beatles", "Capitol");
    c1.addSong(s1);
    c1.addSong(s2);
    cout<< "Using object directly: \n";
    c1.Report();
    
    c1.removeSong(s1);
    

    报告方法如下所示:
    void Cd::Report () const
    {
    
        cout<< "Performers: " << performers << endl << "Label: " <<label << endl << "Selections: " << selections <<endl << "Playtime: " << playtime << endl;
        for(int i = 0; i < selections; i++)
        {
            cout << "Song " << i+1 << ": " << song[i].getTitle() << " Length: " << song[i].getLength() << endl;
        }
    
    }
    

    澄清。我已经用更多的歌曲对此进行了测试,并且没有调用 removeSong 方法,它将写出数组中的所有歌曲。

    编辑** 我正在添加我的其余代码以希望澄清我的问题。我还没有兴趣让它线程安全或更高效,除了向我的导师展示类的继承和组合之外,它没有任何目的,这两者已经超出了我们的任务要求。我很欣赏关于如何使代码更好的评论,并将研究这些事情,但我试图弄清楚为什么当 Report 在主代码中的 removeSong 之前出现时,removeSong 会影响 Report 的输出。我已经测试了不同的方法和重载,它们都按预期工作,这只是我感兴趣的 removeSong 发生的时间。它删除了正确的歌曲并正确地重新排列现有的歌曲,它只是这样做很快:在第一个报告被调用之前。 (我确实需要更改报告中的大写以保持一致性)。我很确定这是一些基本的东西,我在这方面缺少新的东西。

    主要代码:
    // GSP125_Davis_lab4_partA.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <conio.h>
    #include "classic.h"
    #include <string.h>
    ///Prototypes
    void Bravo(const Cd & disk);
    
    Song s1("Hey Jude", 4.52);
    Song s2("the Song of Pie",3.14);
    Song s3("National Anthem", 5.55);
    
    char* userInput = "null";
    char str[20] = "null";
    bool bol_end = false;
    int main()
    {
    
        Cd c1 ("Beatles", "Capitol");
        c1.addSong(s1);
        c1.addSong(s2);
        c1.addSong(s3);
        Cd *pcd = &c1;
        Classic c2("Piano Sonata in B flat, Fantasia in C", "Alfred Brendel", "Phillips");
        c2.addSong(s2);
        c2.addSong(s3);
        c2.addSong(s1);
    
        cout << "Using object directly:\n";
        //this is where the code seems to have an issue. as you see Report is called
        //then after c1.removeSong(s1) is called.  s1 is removed properly but this first
        // c1.Report() reflects the changes removeSong makes.
        c1.Report();
        c2.Report();
        c1.removeSong(s1);
    
        cout << "Using type Cd method for cd object:\n";
    
        pcd->Report();
        pcd = &c2;
        pcd-> Report();
    
        cout<< "Calling a function with a Cd reference argument:\n";
        Bravo(c1);
        Bravo(c2);
    
        cout << "Testing assignment: \n";
        Classic copy;
        copy = c2;
        copy.Report();
    
        cout << "Press any key to continue...";
        _getch();
        return 0;
    
    }
    
    void Bravo(const Cd & disk)
    {
        disk.Report();
    }
    

    光盘
    #include "StdAfx.h"
    #include "cd.h"
    
    
    
    Cd::Cd(char * s1, char * s2) 
    {
        strcpy(performers, s1);
        strcpy(label, s2);
        selections = 0;
        playtime = 0;
        for(int i = 0; i < songLimit; i++)
        {
            song[i] =  Song();
        }
    }
    Cd::Cd(const Cd & d)
    {
        strcpy(performers, d.performers);
        strcpy(label, d.label);
        selections = d.selections;
        playtime = d.playtime;
        for(int i = 0; i < songLimit; i++)
        {
            song[i] = d.song[i];
        }
    }
    Cd::Cd()
    {
        strcpy(performers, "None");
        strcpy(label, "No one");
        selections = playtime = 0;
        for(int i = 0; i < songLimit; i++)
        {
            song[i] = Song();
        }
    }
    
    Cd::~Cd(void)
    {
    }
    void Cd::Report () const
    {
    
        cout<< "Performers: " << performers << endl << "Label: " <<label << endl << "Selections: " << selections <<endl << "Playtime: " << playtime << endl;
        for(int i = 0; i < selections; i++)
        {
            cout << "Song " << i+1 << ": " << song[i].getTitle() << " Length: " << song[i].getLength() << endl;
        }
    
    }
    void Cd::addSong(Song s)
    {
        for (int i = 0; i < songLimit; i++)
        {
    
            if (song[i].getTitle() == "none")
            {
                song[i] = s;
                selections++;
                playtime+= s.getLength();
                break;
            }
        }
    }
    void Cd::removeSong(Song s)
    {
        for (int i = 0; i < songLimit; i++)
        {
            if(song[i] == s)
            {
                song[i] = Song();
                selections--;
                playtime-= s.getLength();
                break;
            }
        }
        organizeSong();
    }
    void Cd::organizeSong() 
    {
    
        int empty = -1;
            for (int i = 0; i < songLimit; i++)
            {
                if(song[i].getTitle() == "none" && empty == -1)
                {
                    empty = i;
                }
                else if (empty != -1)
                {
                    song[empty] = song[i];
                    song[i] = Song();
                    empty = i;
                }
            }
    
    }
    Cd & Cd::operator=(const Cd & d)
    {
        strcpy(performers, d.performers);
        strcpy(label, d.label);
        selections = d.selections;
        playtime = d.playtime;
        for(int i = 0; i < songLimit; i++)
        {
            song[i] = d.song[i];
        }
        return *this;
    }
    

    歌曲.cpp
    #include "StdAfx.h"
    #include "Song.h"
    
    
    
    Song::Song(char* s, double l)
    {
        title = s;
        length = l;
    }
    
    Song::Song(const Song & s)
    {
        title = s.title;
        length = s.length;
    }
    Song::Song()
    {
        title = "none";
        length = 0;
    }
    
    Song::~Song(void)
    {
    }
    
    char* Song::getTitle() const
    {
        return title;
    }
    double Song::getLength() const
    {
        return length;
    }
    Song & Song::operator=(const Song & s)
    {
        title = s.title;
        length = s.length;
        return *this;
    }
    bool & Song::operator==(const Song & s)
    {
        bool result = false;
        if (title == s.title && length == s.length)
        {
            result = true;
        }
        return result;
    }
    

    我再次感谢尝试使代码更高效或更有意义,但我已经做的比老师要求的要多。我只是想知道是否有明显的原因导致在第一次显示报告之前删除歌曲,即使报告在代码中排在第一位。

    最佳答案

    在不知道你的实现的情况下,很难回答你的问题,所以我按照我想象的样子写了它。不过,我做了一些改进:

  • 3.14并不意味着“3 分 14 秒”。充其量就是3.14分钟,也就是3分8.4秒。我已将其更改为明确的 chrono原语
  • 由于歌曲之间的相等关系不明确,按值删除歌曲是模棱两可的。我注意到你已经重载了operator== ,但我看不出如何合理地实现这一点。为每首歌曲添加一个唯一的 id 是解决问题的一种方法,但我觉得没有资格这样做,所以我决定按索引删除(这也很好地模拟了 CD 本身)。
  • 收藏 不是线程安全的 .不要忘记这一点。
  • 不知道为什么report是大写的,但我改变了它以保持一致性。

  • 我不确定 CD 内部的重组应该如何工作,所以我跳过了那部分。
    #include <iostream>
    #include <list>
    #include <functional>
    #include <chrono>
    #include <string>
    #include <stdexcept>
    #include <iterator>
    
    // C++14-like shim
    // in C++14 just use min and s
    constexpr std::chrono::minutes operator "" _min(unsigned long long m) {
        return std::chrono::minutes(m);
    }
    constexpr std::chrono::seconds operator "" _s(unsigned long long s) {
        return std::chrono::seconds(s);
    }
    
    class Song {
    public:
        std::string title;
        std::chrono::seconds length;
    
        Song(std::string title, std::chrono::seconds length) :
            title(std::move(title)), length(length) { }
    };
    
    class Cd {
        std::list<std::reference_wrapper<Song>> songs;
        std::string performer, title;
    
    public:
        void addSong(Song & s) {
            songs.push_back(std::ref(s));
        }
        void removeSong(unsigned n) {
            if (n >= songs.size())
                throw std::out_of_range("The song of given index doesn't exist on that album");
    
            songs.erase(std::next(songs.begin(), n));
        }
        void report() const {
            std::cout << title << ", " << performer << '\n';
            for (auto const& song : songs) {
                std::cout << song.get().title << " " 
                          << song.get().length.count() / 60 << ":"
                          << song.get().length.count() % 60 << '\n';
            }
            std::cout << std::endl;
        }
    
        Cd(std::string performer, std::string title) :
            performer(std::move(performer)), title(std::move(title))
        { }
    };
    
    int main() {
        Song s1("Hey Jude", 4_min + 52_s);
        Song s2("The song of Pie", 3_min + 14_s);
    
        Cd c1 ("Beatles", "Capitol");
        c1.addSong(s1);
        c1.addSong(s2);
        c1.report();
    
        // this doesn't work anymore because of the reasons described above
        //c1.removeSong(s1);
        c1.removeSong(0);
        c1.report();
    }
    

    关于C++ 类方法在其他方法之前运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21503846/

    相关文章:

    c++ - 使用指针符号循环遍历数组

    c++ - 使 Qt Player 编解码器独立

    c++ - 多种字体大小的 FreeType 字形指标缓存

    c++ - 启用 C++11 时如何修复 'wrong number of template arguments''?

    c++ - 您会为经验丰富的程序员推荐什么 C++ 教程,该程序员对该语言有一些零散的了解?

    c++ - C++ 如何检测它正在运行的当前线程?

    C++ 指针对象在函数之外丢失?

    c++ - 我的缓冲区包含元素,但未被打印

    c++ - 从 C++ 函数返回字符串数组

    c++ - 两个不同大小的硬编码数组到一个二维 vector 中