Answer the question
In order to leave comments, you need to log in
What will the abstract class contain?
There is a seemingly simple learning task for C++: implement linked list, dynamic array, and static array classes. All three classes must inherit from the same abstract class.
It seems to be clear what a dynamic array can have in common, there is a pointer to the first element, an access method by index.
But the implementation of a static array generally somehow does not fit with the rest. To what extent does this part of the task correspond to common sense and real tasks? In my inexperienced opinion, there is already a regular built-in array and in the implementation of a dynamic array it should be used as a data field. I have no idea how to implement my own static array.
Answer the question
In order to leave comments, you need to log in
In your case, the base class should have a pointer to the first element, a method to access by index, and a method to get the number of elements in the array. Perhaps, during the execution, highlight something else they have in common.
To implement a static array in the constructor, allocate memory for the required number of elements, and when accessing by index - just make an offset from the pointer to the first element - that's the implementation of the standard array
can you arrange the same interface for linked list and static array? You can. That's the whole answer.
In this case, the rest of the code will be tied to the abstract class that describes the interface, and it doesn’t matter which implementation you slip in. This is called subtype polymorphism.
Option one you suggested. I write everything in C++03, without templates. C++11 and templates will of course give you more options.
class Object {
public:
virtual ~Object() {}
};
class List { // interface
protected:
virtual Object& getAt(size_t i) = 0;
public:
virtual size_t size() const = 0;
inline Object& at(size_t i) { return getAt(i); }
inline const Object& at(size_t i) const
{ return const_cast<List*>(this)->getAt(i); }
virtual ~List() {}
};
class ListCallback { // interface
public:
virtual void act(size_t index, Object& object) = 0;
virtual ~ListCallback() {}
};
class ListConstCallback { // interface
public:
virtual void act(size_t index, const Object& object) = 0;
virtual ~ListConstCallback() {}
};
class List2 { // interface
public:
virtual size_t size() const = 0;
virtual void enumerate(ListCallback& body) = 0;
virtual void enumerate(ListConstCallback& body) const = 0;
};
void DynArray::enumerate(ListConstCallback& body) const {
size_t sz = size();
for (size_t i = 0; i < sz; ++i)
body(i, operator[](i));
}
class VirtualListIterator { // interface
public:
virtual bool next() = 0;
virtual Object& value() = 0;
virtual ~VirtualListIterator() {}
};
class ListIterator { // Назван так для красоты, по сути это умный указатель
private:
VirtualListIterator* ptr;
// Запретим копирование и op=, но при желании можно реализовать и их
ListIterator(ListIterator&) {}
void operator=(const ListIterator&) {}
public:
ListIterator() : ptr(NULL) {}
ListIterator(VirtualListIterator* value) : ptr(value) {}
~ListIterator() { delete ptr; }
bool next() { return ptr->next(); }
Object* operator->() const { return &ptr->value(); }
Object& operator*() const { return ptr->value(); }
};
class List3 { // interface
public:
virtual size_t size() const = 0;
virtual VirtualListIterator* enumerate() = 0;
};
class Number : public Object {
public:
int value;
};
// И пользоваться этим так...
void doSmth(List3& aList) {
ListIterator it(aList.enumerate());
while (it.next()) {
std::cout << dynamic_cast<Number&>(*it).value << std::endl;
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question