0

I defined the following abstract List class:

#ifndef LIST_H
#define LIST_H

template <class T>
class List
{
    public:
        List();

        virtual bool isEmpty() const=0;
        virtual void Set(int index, T value)=0;
        virtual int getSize() const=0;
        virtual void add(T value)=0;
        virtual T Remove(int index)=0;
        virtual ~List();
        
    protected:

        int m_size;

    private:
};
#endif // LIST_H

And then I defined a succesor DynamicArray:

#ifndef DYNAMICARRAY_H
#define DYNAMICARRAY_H
#include <iostream>
#include "List.h"
#define CAPACITY 15


template<class T>
class DynamicArray : public List<T>
{
    public:
    //|========================Constructors============================

        DynamicArray(): m_size(0), m_capacity(CAPACITY) {                   //|Default constructor
            m_data = new T[CAPACITY];
        }
 protected:


    private:

        //|========================Private Fields=========================
        int m_capacity;
        T* m_data;
        
};

(This is not the full class definition, of course I implemented a destructor and more methods but it does not concern my problem).

For some reason I get the following error:

 'm_size' was not declared in this scope| 

But m_size is defined in the base abstract class "List" and DyanamicArray inherits from List. So what went wrong here?

Thanks in advance.

  • 1
    Try `this->m_size` instead. – songyuanyao Jan 25 '22 at 02:16
  • @songyuanyao It works. But why cant I use this field as any other field ? – DirichletIsaPartyPooper Jan 25 '22 at 02:22
  • 4
    [Derived template-class access to base-class member-data](https://stackoverflow.com/a/24368629/3309790) – songyuanyao Jan 25 '22 at 02:24
  • Template name issues aside, a derived class constructor's member init list can't initialize a base class member. (The derived constructor body can assign it if `protected` or `public`, but I agree with the answer by Christoph that it's better to have the base class initialize it.) – aschepler Jan 25 '22 at 12:11

1 Answers1

2

Add a constructor List(int) to the base class which initializes the m_size field.

template <class T>
class List
{
    public:
        List();
        List(int _size): m_size(_size) {};
    // .... 
    protected:
        int m_size;
};

Add this constructor to the initializers of DynamicArray:

template<class T>
class DynamicArray : public List<T>
{
public:
    DynamicArray(): List<T>(CAPACITY), m_capacity(CAPACITY) {                   
        m_data = new T[CAPACITY];
    }
private:
    int m_capacity;
    T* m_data;
};

Base initializers can set const fields. What DynamicArray(): m_size(0) is trying to do is:

  1. initialize DynamicArray
  2. initiatlize List with default constructor
  3. set m_size

Step 3 is not allowed (what if m_size is const?).

In terms of Software Architecture, classes should be responsible for initializing their own fields. Otherwise making changes to the internals of a base class will break child classes.

Christoph
  • 386
  • 1
  • 4