shell — Делегирование конструкторов с наследованием в эмуляции файловой системы C ++ FAT

В настоящее время я создаю файловую систему FAT на C ++. У меня есть три класса:

  • Sdisk (форматирует диск через строку для вывода в файл).
  • Filesys (который пишет FAT и рут).
  • Оболочка (предлагает возможность выполнять различные операции с файловой системой.)

Во время кодирования каждого класса я писал простые основные инициализации конструкторов Sdisk и Filesys. Теперь, когда я пишу Shell, когда я тестирую конструктор Shell по умолчанию, у меня возникают проблемы с памятью. В частности: EXC_BAD_ACCESS (код = 1 адрес = 0xfffffffffffffff ….).

Я решил использовать свой отладчик, чтобы выяснить, что пошло не так, и определил, что значения, которые я передавал в конструкторе Shell в конструктор по умолчанию Sdisk, были неправильными. Я начал копать и обнаружил, что вызывается другой конструктор классов внутри текущего конструктора классов: «Делегирование» или «Цепочка конструктора». Не имел представления. Я обнаружил, что вы должны «использовать его из списка инициализации, а не из тела конструктора».

Я создал дополнительный конструктор без параметров для Shell. Что мне нужно сделать, так это вызвать Sdisk из конструктора Shell с тремя параметрами Sdisk по умолчанию. Но когда я пытаюсь это сделать, я продолжаю получать ошибки памяти. Я даже пытался дать конструктору по умолчанию Shell никаких параметров, но пока я вызываю его в main, это вызывает ошибку.

Любая помощь по этому вопросу чрезвычайно ценится! Спасибо!

Вот моя ссылка для делегирования конструкторов

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;
}

2

Решение

Проблема здесь:

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

Shell Конструктор создает в теле временный объект оболочки, который снова вызывает конструктор Shell и так далее. Таким образом, вы получите бесконечную рекурсию и полный стек.

Другие замечания:

  • В вашем конструкторе оболочки вы также инициализируете подобъект базового класса с помощью mem-initializer Filesys(disk), Я не мог найти действительный disk в вашем фрагменте кода. Но поскольку вы испытываете проблемы во время выполнения, а не ошибки компиляции, я полагаю, что он просто потерян в копии&вставить.

  • Вы уверены, что Shell должен наследовать от Filesys ? То есть Вы можете сказать, что ваш Shell это FAT файловая система? И как будет развиваться дизайн вашего класса, если впоследствии вы решите обогатить файловые системы, которые поддерживает ваш Shell, например, файловые системы NTFS или EXT3?

  • Наконец, количество блоков и размер блока — это не параметры файловой системы, а не оболочка, которую вы строите на ее вершине?

По этим причинам я бы предпочел что-то вроде:

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
1

Другие решения

Надеюсь, я понял это правильно. У вас довольно много проблем в вашем коде. Как я уже сказал в комментарии, это очень плохо:

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

Это очевидная бесконечная рекурсия. Вы сказали, что вам нужно позвонить Sdisk изнутри Shell так что, я думаю, вы имели в виду

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

Однако это никак не поможет. Такой синтаксис создаст временный Sdisk который умрет немедленно. Вы сказали, что хотите использовать параметр по умолчанию, но нигде не предоставляете.

Вообще ваш дизайн довольно плохой. Отношения между классами не ясны, и вы получили странные решения, которые не имеют особого смысла. То есть почему вы хотите вызвать этот конструктор? Какова связь между Sdisk а также Shell? В оболочке нет переменных-членов, поэтому она не может содержать состояния (я почти уверен, что она не предназначена) … и т. Д.

0

По вопросам рекламы [email protected]