c++ - 在 C++ FAT 文件系统仿真中使用继承委派构造函数

标签 c++ shell oop constructor fat

我目前正在用 C++ 创建一个 FAT 文件系统。我有三个类(class):

  • Sdisk(通过字符串格式化磁盘到文件输出)。
  • Filesys(写入 FAT 和根目录)。
  • Shell(提供执行各种文件系统操作的能力。)

在每个类编码过程中,我编写了 Sdisk 和 Filesys 构造函数的简单主要初始化。现在我正在编写 Shell,当我测试 Shell 的默认构造函数时,我遇到了内存问题。具体来说:EXC_BAD_ACCESS(code=1 address=0xfffffffffffffff....)。

我决定使用我的调试器找出问题所在,并确定我在 Shell 构造函数中传递给 Sdisk 默认构造函数的值不正确。我开始挖掘并发现在当前类构造函数中调用另一个类构造函数被称为:“Delegating”或“Constructor Chaining”。我不知道。我发现你必须“从初始化列表中使用它,而不是从构造函数体中使用它”。

我已经为 Shell 创建了一个没有参数的额外构造函数。我需要做的是使用 Sdisk 的默认三个参数从 Shell 构造函数内部调用 Sdisk。但是当我尝试这样做时,我继续出现内存错误。我什至尝试不给 Shell 的默认构造函数任何参数,但只要我在 main 中调用它就会导致错误。

非常感谢有关此事的任何帮助!谢谢!

Here is my reference for Delegating Constructors

class Shell: public Filesys
{
    public:    
    Shell(string filename, int blocksize, int numberofblocks):Filesys(disk) {Filesys(filename,blocksize,numberofblocks);};                // creates the file system.
        int dir();              // call ls which lists all files
        int add(string file);   // add a new file using input from the keyboard.
        int del(string file);   // deletes the file
        int type(string file);  //lists the contents of file
        int copy(string file1, string file2);//copies file1 to file2
    friend class Sdisk;
    friend class Filesys;
};



class Sdisk
{
    public :
    Sdisk() { }

    Sdisk(string diskname);                                         // Default Constructor
    Sdisk(string diskname, int numberofblocks, int blocksize);
    int getblock(int blocknumber, string& buffer);
    int putblock(int blocknumber, string buffer);
    int getblocksize() {return blocksize; }                         // Returns the blocksize.
    int getnumberofblocks() { return numberofblocks; }              // Returns the number of blocks.
    string getfilename() { return diskname; }                       // Returns the disk name.
    friend class Shell;
    friend class Filesys;

    private :

    int numberofblocks;                                             // number of blocks on disk
    string diskname;                                                // file name of pseudo-disk
    string diskname1;
    int blocksize;                                                  // block size in bytes/the number of blocks.
};

  class Filesys
{
public:

    Filesys(Sdisk&);
    int fsclose();
    int newfile(string file);
    int rmfile(string file);
    int getfirstblock(string file);
    int addblock(string file, string block);
    int delblock(string file, int blocknumber);
    int readblock(string file, int blocknumber, string& buffer);
    int writeblock(string file, int blocknumber, string buffer);
    int nextblock(string file, int blocknumber);
    bool checkblock(string file, int blocknumber);
    vector<string> block(string buffer, int b);
    Sdisk disk;
    friend class Shell;

    private :

    int fssync();                   //writes the Root and FAT to the disk.
    string buffer;
    int rootsize;                   // maximum number of entries in ROOT
    int fatsize;                    // number of blocks occupied by FAT
    vector<string> filename;        // filenames in ROOT
    vector<int> firstblock;         // firstblocks in ROOT parallel
    vector<int> fat;                // FAT # of blocks
};

int main()
{   
    Shell("disk",256,128);
    string s;
    string command="go";
    string op1,op2;

    while (command != "quit")
    {
        command.clear();
        op1.clear();
        op2.clear();
        cout << "$";
        getline(cin,s);
        unsigned long firstblank = s.find(' ');
        if (firstblank < s.length()) s[firstblank]='#';
        unsigned long secondblank = s.find(' ');
        command=s.substr(0,firstblank);
        if (firstblank < s.length())
            op1=s.substr(firstblank+1,secondblank-firstblank-1);
        if (secondblank < s.length())
            op2=s.substr(secondblank+1);
        if (command=="dir")
        {
            cout << "dir" << endl;

            // use the ls function

        }
        if (command=="add")
        {
            // The variable op1 is the new file
            cout << "add" << endl;

        }
        if (command=="del")
        {
            cout << "del" << endl;
            // The variable op1 is the file
        }
        if (command=="type")
        {
            cout << "type" << endl;
            // The variable op1 is the file
        }
        if (command=="copy")
        {
            cout << "copy" << endl;
            // The variable op1 is the source file and the variable op2 is the destination file.
        }
        if (command=="exit")
        {
            cout << "Exiting now..." << endl;
            return 0;
        }

    }

    return 0;
}





Filesys::Filesys(Sdisk& sdisk):Sdisk(disk)
{
    this-> disk = sdisk;
    rootsize = disk.getblocksize()/12;
    fatsize = (disk.getnumberofblocks()*5) / (disk.getblocksize())+1;
    cout << "rootsize: " << rootsize << endl << "fatsize: " << fatsize << endl << "number of blocks: " <<  disk.getnumberofblocks() << endl << "getblocksize(): " << disk.getblocksize() << endl;

    for(int i=0; i<rootsize; i++)
    {
        filename.push_back("XXXXXX");
        firstblock.push_back(0);
    }

    int k= disk.getnumberofblocks();
    fat.push_back(fatsize + 2);

    for (int i = 0; i <= fatsize; i++)
    {
        fat.push_back(0);

    }

    for(int i = fatsize + 2; i < k; i++)

    {
        fat.push_back(i+1);
    }
    fat[fat.size()-1] = 0;
    fssync();
}


Sdisk::Sdisk(string disk)
{
    diskname = disk + ".dat";
    diskname1 = disk + ".spc";
    ifstream ifile(diskname1.c_str());

    if(ifile.is_open())
    {
        ifile >> numberofblocks >> blocksize;
        ifile.close();
    }

    else
    {
        cout << "Was unable to open the file" << endl;
    }
}

// Sdisk default constructor
Sdisk::Sdisk(string disk, int numberofblocks, int blocksize)
{
    this->diskname = disk + ".dat";
    this->diskname1 = disk + ".spc";
    this->numberofblocks = numberofblocks;
    this->blocksize = blocksize;
    fstream spcfile;
    fstream datfile;
    spcfile.open((this->diskname1).c_str(),ios::in | ios::out);
    datfile.open((this->diskname).c_str(),ios::in | ios::out);

    if (spcfile.good() && datfile.good())
    {
        cout << "The disk named: " << diskname.c_str() << " exists and is now ready to be written to." << endl;
    }
    else // .spc/.dat file creation.
    {
        cout << "The disk: " << diskname.c_str() << "could not be found. " << endl;
        cout << "Both the SPC and DAT file were not found. Creating both now. Please wait...." << endl;
        spcfile.open((this->diskname1).c_str(),ios::out);
        datfile.open((this->diskname).c_str(),ios::out);
        spcfile << numberofblocks << " " << blocksize;
        cout << "The SPC file " << diskname.c_str() << " was created" << endl;
        cout << "The DAT file " << diskname.c_str() << " was created" << endl;

        for (int i=0; i<numberofblocks*blocksize; i++)
        {
            datfile.put('#');           // Fills the file with '#' character.
        }
    }
    spcfile.close();
    datfile.close();
    return;
}

最佳答案

问题出在这里:

Shell(string filename, int blocksize, int numberofblocks) : Filesys(disk) 
{
   Shell(filename,blocksize,numberofblocks);
};

Shell 构造函数在主体中创建一个临时 shell 对象,它本身再次调用 Shell 构造函数,依此类推。所以你最终会得到一个无限递归和一个完整的堆栈。

其他备注:

  • 在您的 shell 构造函数中,您还使用 mem-initializer Filesys(disk) 初始化了基类子对象。我在您的代码片段中找不到有效的 disk。但是当您遇到运行时问题而不是编译错误时,我想它只是在复制和粘贴过程中丢失了。

  • 您确定 Shell 应该继承自 Filesys 吗? IE。你能说你的 Shell 是一个 FAT 文件系统吗?如果稍后您决定使用 NTFS 或 EXT3 文件系统来丰富您的 Shell 支持的文件系统,您的类设计将如何发展?

  • 最后, block 数和 block 大小不是文件系统的参数,而不是您在其顶部构建的 shell 的参数吗?

出于这些原因,我宁愿去做类似的事情:

class Shell
{
    string fname; 
    Filesys &fs;  
public:    
    Shell(string filename, Filesys &filesystem) 
        : fname(filename), fs(disk)
    { ... };                // creates the file system.
    ...
};

在这种情况下,您将创建 Shell:

Sdisk mydisk("drive1", 32768, 4096);  // disk data for the disk constructor
Filesys mysystem(mydisk);             // fs parameters for the fs
Shell myshell("A:", mysystem);        // higher level abstraction 

关于c++ - 在 C++ FAT 文件系统仿真中使用继承委派构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30279684/

相关文章:

c++ - 使用参数包将 lambda 转换为 std::function

shell - 进程完成后读取 stderr

python - 如何重定向 cron 脚本的完整输出

database - 使用 Delphi 进行数据库开发的最佳实践是什么?

c++ - malloc_consolidate 中的 SIGABRT - __FUNCTION__ 是否有可能返回 NULL?

c++ - 关闭时出现访问冲突错误

linux - 如何解析正确的版本号?

matlab - 有没有办法找到一个 Matlab 类的所有 child ?

java - 面向对象代码,非面向对象语言

c++ - 将带有引号和逗号的字符串文件读入字符串数组