3

I have a class template "Stack" which is used to make a stack data structure. Another class template "specialStack" (inheriting "stack" class publicly) it is used to get a minimum element from the stack in O(1) time complexity - getMin() does this work.

I have an error in inheriting isEmpty() from the base class. It's showing isEmpty() un-declared identifier (as you can see in the below screenshot). I have found that to resolve this issue we have to again override the function in the derived class but if we have lots of functions in the base class then it is not possible to override all the functions. I have also tried the second method to solve this issue by using stack< T >::isEmpty() in the derived class but now it's giving me another bunch of errors.

Here is my code:-

#include<iostream>
using namespace std;
template<class T>
class stack {
    static const int max = 100;
    int arr[max];
    int top = -1, size = max;
public:
    void push(T x);
    T pop();
    int isEmpty();
    T topElement();
};
template<class T>
int stack<T>::isEmpty() {
    if (top == -1) return 1;
    return 0;
}
template<class T>
void stack<T>::push(T x) {
    if (top!=size) arr[++top] = x;
}
template<class T>
T stack<T>::pop() {
    if (top != -1)
    {
        return arr[top--];
    }
}
template<class T>
T stack<T>::topElement() {
    if (top != -1) return arr[top];
}
template<class T>
class specialStack : public stack<T> {
    stack<T>min;
public:
    void push(T x);
    T pop();
    T getMin();
};
template<class T>
void specialStack<T>::push(T x) {
    if (isEmpty()) {
        min.push(x);
        stack::push(x);
    }
    else {
        T y = min.topElement();
        if (x < y)
        {
            stack::push(x);
            min.push(x);
        }
        else {
            stack::push(x);
            min.push(y);
        }
    }
}
template<class T>
T specialStack<T>::pop() {
    if (true)
    {
        min.pop();
        stack::pop();
    }
}
template<class T>
T specialStack<T>::getMin() {
    return min.topElement();
}
int main() {
    specialStack<int>st;
    st.push(1);
    st.push(2);
    st.push(3);
    st.push(4);
    st.push(5);
    st.push(6);
    cout << st.getMin();
}

Here is the error screenshot :

pradeexsu
  • 1,029
  • 1
  • 10
  • 27
  • Try `stack::isEmpty()` – NutCracker Oct 23 '20 at 06:20
  • `using Base = stack;` and `Base::isEmpty()` (`Base::push(x)` and so on). – dfrib Oct 23 '20 at 06:20
  • 1
    Are you looking for an explanation ([Why do I have to access template base class members through the this pointer?](https://stackoverflow.com/questions/4643074/)) or for workarounds ([Derived template-class access to base-class member-data](https://stackoverflow.com/questions/1120833/))? – JaMiT Oct 23 '20 at 07:03

3 Answers3

3

You should be passing template parameter T to the base class stack too, because it is a template class, and then call all its functions with stack<T>:: scope operator.

So you would have:

stack<T>::push(x);

and

stack<T>::isEmpty();
NutCracker
  • 11,485
  • 4
  • 44
  • 68
3

In the definition of specialStack, stack<T> is a dependent name; dependent on the type template parameter T of specialStack.

A common approach to solve this is to define a utility type alias to the base class stack specialization for the specific T:

class specialStack : public stack<T> {
    // stack<T> is a dependent name here.
    using Base = stack<T>;  // note: this can be private, and use
                            // solely for implementation ease.
    // ...
};

after which you can call the member functions of the dependent base class type stack<T> via the utility alias

Base::isEmpty();

// ...

Base::push(x); // ...  and so on.

Alternative, you can qualify each specific call to base class member functions with stack<T>

stack<T>::isEmpty();

// ...

stack<T>::push(x);  //...  and so on.
dfrib
  • 70,367
  • 12
  • 127
  • 192
2

To use parent function in a child class you need to specify the namespace of the function in this way

stack<T>::isEmpty()

when you use it in the child class.

So the code result is the following :

#include<iostream>
using namespace std;
template<class T>
class stack {
    static const int max = 100;
    int arr[max];
    int top = -1, size = max;
public:
    void push(T x);
    T pop();
    int isEmpty();
    T topElement();
};
template<class T>
int stack<T>::isEmpty() {
    if (top == -1) return 1;
    return 0;
}
template<class T>
void stack<T>::push(T x) {
    if (top!=size) arr[++top] = x;
}
template<class T>
T stack<T>::pop() {
    if (top != -1)
    {
        return arr[top--];
    }
}
template<class T>
T stack<T>::topElement() {
    if (top != -1) return arr[top];
}
template<class T>
class specialStack : public stack<T> {
    stack<T>min;
public:
    void push(T x);
    T pop();
    T getMin();
};
template<class T>
void specialStack<T>::push(T x) {
    if (stack<T>::isEmpty()) {
        min.push(x);
        stack<T>::push(x);
    }
    else {
        T y = min.topElement();
        if (x < y)
        {
            stack<T>::push(x);
            min.push(x);
        }
        else {
            stack<T>::push(x);
            min.push(y);
        }
    }
}
template<class T>
T specialStack<T>::pop() {
    if (true)
    {
        min.pop();
        stack::pop();
    }
}
template<class T>
T specialStack<T>::getMin() {
    return min.topElement();
}
int main() {
    specialStack<int>st;
    st.push(1);
    st.push(2);
    st.push(3);
    st.push(4);
    st.push(5);
    st.push(6);
    cout << st.getMin();

}
Zig Razor
  • 3,381
  • 2
  • 15
  • 35