Я изучаю C ++ самостоятельно, и я подумал, что хороший способ испачкать руки - это конвертировать некоторые проекты Java в C ++, посмотрите, где я упал. Так что я работаю над реализацией полиморфного списка. Работает нормально, за исключением одной странной вещи.
Способ, которым я печатаю список, заключается в том, чтобы класс EmptyList
возвращал "null" (строка, а не указатель), а NonEmptyList
возвращает строку, в которой их данные объединены с результатом вызова tostring()
on все остальное в списке.
Я помещаю tostring()
в секцию protected
(это казалось уместным), и компилятор жалуется на эту строку (s
- это stringstream
, который я использую для накопления строки):
s << tail->tostring();
Вот ошибка от компилятора:
../list.h: In member function 'std::string NonEmptyList::tostring() [with T = int]':
../list.h:95: instantiated from here
../list.h:41: error: 'std::string List::tostring() [with T = int]' is protected
../list.h:62: error: within this context
Вот большая часть list.h
:
template <class T> class List;
template <class T> class EmptyList;
template <class T> class NonEmptyList;
template <typename T>
class List {
public:
friend std::ostream& operator<< (std::ostream& o, List<T>* l){
o << l->tostring();
return o;
}
/* If I don't declare NonEmptyList<T> as a friend, the compiler complains
* that "tostring" is protected when NonEmptyClass tries to call it
* recursively.
*/
//friend class NonEmptyList<T>;
virtual NonEmptyList<T>* insert(T) =0;
virtual List<T>* remove(T) =0;
virtual int size() = 0;
virtual bool contains(T) = 0;
virtual T max() = 0;
virtual ~List<T>() {}
protected:
virtual std::string tostring() =0;
};
template <typename T>
class NonEmptyList: public List<T>{
friend class EmptyString;
T data;
List<T>* tail;
public:
NonEmptyList<T>(T elem);
NonEmptyList<T>* insert(T elem);
List<T>* remove(T elem);
int size() { return 1 + tail->size(); }
bool contains(T);
T max();
protected:
std::string tostring(){
std::stringstream s;
s << data << ",";
/* This fails if List doesn't declare NonEmptyLst a friend */
s << tail->tostring();
return s.str();
}
};
Таким образом, объявление NonEmptyList
другом List
устраняет проблему, но кажется странным объявить производный класс в качестве друга базового класса.