невозможно преобразовать параметр 1 из PrintVisitor * const в Visirot & amp;

Я использовал два дизайна шаблона Composite и Visitor. У меня нет проблем с Composite. Но когда он начал писать производные классы для ввода и вывода, получилось несколько ошибок, решение которых я так и не нашел. Хотя на самом деле и если все будет InputVisitor сделано так осталось только PrintVisitor а также главный().

Вот мой код:

UPD: Я переписываю некоторые части кода. Теперь у меня нет ошибок, но он только открывает терминал и ничего не делает …

Постскриптум Возможно я не правильно реализовал шаблоны. У кого-то есть идея получше?

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

class BaseComponent {
public:
virtual void add(BaseComponent *)=0;
virtual void accept(class Visitor &)=0;
};

class Card :public BaseComponent {
public:
Card (string bookName, vector<string> authors, int year): _bookName(bookName), _authors(authors), _year(year) {}

string getBookName() const {
return _bookName;
}
vector<string> getAuthors() const {
return _authors;
}
int getYear() const {
return _year;
}

void setBookName(string bookName) {
_bookName = bookName;
}
void setAuthors(vector<string> authors) {
copy(authors.begin(), authors.end(), _authors.begin());
}
void setYear(int year) {
_year = year;
}

void add(BaseComponent *){}
void accept(class Visitor &);
private:
string _bookName;
vector<string> _authors;
int _year;
};

class Folder :public BaseComponent {
public:
Folder(): _folderName(""), _parentFolder("") {}
Folder(string parentFolder): _folderName(""), _parentFolder(parentFolder) {}

string getFolderName() const {
return _folderName;
}
string getParentName() const {
return _parentFolder;
}
vector<BaseComponent*> getSubFolders() const {
return _subFolders;
}

void setFolderName(string folderName) {
_folderName = folderName;
}
void setParentFolder(string parentFolder) {
_parentFolder = parentFolder;
}

void add(BaseComponent *component) {
_subFolders.push_back(component);
}
void accept(class Visitor &);
private:
string _folderName;
string _parentFolder;
vector<BaseComponent*> _subFolders;
};

class Visitor {
public:
virtual void visitCard(Card *)=0;
virtual void visitFolder(Folder *)=0;
};

void Card::accept(class Visitor &visitor) {
visitor.visitCard(this);
}

void Folder::accept(class Visitor &visitor) {
visitor.visitFolder(this);
}

class InputVisitor :public Visitor {
public:
InputVisitor(string file): _file(file){}

void setFile(string file) {
_file = file;
}

void visitCard(Card *){}
void visitFolder(Folder *folder){
ifstream input(_file);

string folderName;
getline(input, folderName);
folder->setFolderName(folderName);

string fileName;
while (!input.eof()) {
input >> fileName;
if (fileName == "----") {
break;
} else {
Folder *subFolder = new Folder(folderName);
InputVisitor *inputVisitor = new InputVisitor(fileName);
subFolder->accept(*inputVisitor);
folder->add(subFolder);
}
}
while (!input.eof()) {
string name, tempAuthor;
vector<string> authors;
int n, year;

input >> name;
input >> n;
for (int i = 0; i<n; ++i) {
input >> tempAuthor;
authors.push_back(tempAuthor);
}
input >> year;
Card *subBook = new Card(name, authors, year);
folder->add(subBook);
}
input.close();
}
private:
string _file;
};

class PrintVisitor :public Visitor {
public:
PrintVisitor(string outputFile): _outputFile(outputFile) {}

void setOutputFile(string outputFile) {
_outputFile = outputFile;
}

void visitFolder(Folder *folder) {
ofstream output(_outputFile);
output << folder->getFolderName() << endl << "\t";

vector<BaseComponent*> subFolders = folder->getSubFolders();
vector<BaseComponent*>::iterator it;
for (it=subFolders.begin(); it!=subFolders.end(); ++it) {
(*it)->accept(*this);
}

output.close();
}
void visitCard(Card *card) {
ofstream output(_outputFile);
output << "Book: " << card->getBookName() << endl
<< "Author(s): ";
vector<string> authors = card->getAuthors();
for (vector<string>::iterator it=authors.begin(); it!=authors.end(); ++it) {
output << *it << " ";
}
output << endl << "Year: " << card->getYear();

output.close();
}
private:
string _outputFile;
};int main() {
Folder root;
root.accept(*(new InputVisitor("root.txt")));
root.accept(*(new PrintVisitor("output.txt")));
return 0;
}

0

Решение

В этом коде:

InputVisitor *input;
input->setFile("root.txt");
root->accept(input);  //Here

InputVisitor является * входом. Ваша функция принятия принимает ссылку на посетителя. Измените это на:

root->accept(*input);  //Here

и все будет хорошо, кроме опечатки, которую я упомянул в комментарии.

Если вы удалите все class перед именами для классов компилятор сообщит вам, когда есть имя класса с ошибкой. В противном случае он будет воспринимать это как «класс с именем Visirot в какой-то момент в будущем, и мне все равно, что в этом сейчас.

0

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

Вот декларация BaseComponent::accept:

virtual void accept(class Visirot &)=0;

Вот звонок:

root->accept(input);  //Here

Вот декларация input:

InputVisitor *input;

Итак, во-первых, декларация BaseComponent::accept по-видимому, опечатка; Visirot должно быть Visitor,

Во-вторых, accept занимает Visitor&, но это вызывается с InputVisitor*, InputVisitor происходит от Visitor, soInputVisitor *is convertible toПосетитель *andInputVisitor&is convertible toпосетитель&, but there is no conversion from a pointer-to-type into a reference-to-type. So either changeBaseComponent :: accept` для получения указателя или изменения вызова для передачи ссылки.

0

Первая проблема

Предполагая опечатку Visirot фиксируется, то в строке 152 у вас есть

subFolders[i]->accept(this); //Here some probrem

который передает указатель на T, где ожидается T.

Просто разыщите этот указатель:

subFolders[i]->accept(*this);

Вторая проблема

Применение тех же исправлений в основной программе будет неправильно:

int main() {
BaseComponent *root;
InputVisitor *input;
input->setFile("root.txt");
root->accept(*input);  //Here
PrintVisitor *output;
output->setOutputFile("output.txt");
root->accept(output); //And here
return 0;
}

Это разыменовывает неинициализированные указатели, что приводит к Неопределенное поведение.

Не делай этого.

Перепишите его, например, как

int main() {
Folder root;
InputVisitor input;
input.setFile("root.txt");
root.accept(input);  //Here
PrintVisitor output;
output.setOutputFile("output.txt");
root.accept(output); //And here
}

(и, возможно, заменить Folder с любым конкретным классом вы хотите там.)

Третья проблема

В строке 144 вы назначаете потоку:

_outputFile = ofstream(outputFile);

где _outputFile является членом типа ofstream, а также outputFile это string,

При этом используется функция C ++ 11 (присваивание rvalue потоков), которую g ++ не реализовала в версии 4.7.1.

Предположительно, идея заключается в том, чтобы закрыть _outputFile и снова откройте его: просто сделайте это, и код будет гораздо более переносимым:

// Add failure checking:
_outputFile.close();
_outputFile.open( outputFile );

Кроме того, было бы неплохо более наглядное именование …

Общая проблема задана в данном коде.

Компиляция выше приводит к ряду предупреждений о сравнении со знаком и без знака и неиспользуемых локальных переменных. Исправить все это. Построить на самом высоком уровне практического предупреждения, -Wall с g ++ и /W4 с Visual C ++, и сделайте его аккуратным.

Логические ошибки & тестирование.

Даже когда он компилируется чисто, логические ошибки могут и всегда будут оставаться. Чтобы искоренить их, разработайте набор точно воспроизводимый тесты, дополненные необходимыми данными испытаний.

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