C++, Template i dziedziczenie

Źródła:

base_basket.hpp:

#ifndef BASE_BASKET_HPP

#define BASE_BASKET_HPP


#include

#include


template

class Basket {

    protected:

        _Cl *storage;

        _T_prio *priorities;

        unsigned int size;


        virtual bool isgreater(unsigned int &i, unsigned int &j) const =0;


    public:

        Basket();

        Basket(const unsigned int &_size);

        Basket(const Basket &basket);

        virtual ~Basket();


        Basket& operator=(const Basket &basket);


        unsigned int getsize() const;

        /* _CL add(_CL &addthis);

        void remove(unsigned int i);

        bool remove(_CL &smthglikethat);

        bool isin(_CL &smthglikethat);*/

};


template

Basket<_Cl, _T_prio>::Basket() {

    storage = NULL;

    priorities = NULL;

    size = 0u;

    std::clog << "Basket default constructor" << std::endl;

}


template

Basket<_Cl, _T_prio>::Basket(const unsigned int &_size) {

    size = _size;

    if(size == 0u) {

        storage = NULL;

        priorities = NULL;

    }

    else {

        storage = new _Cl[size];

        priorities = new _T_prio[size];

    }

    std::clog << "Basket size constructor" << std::endl;

}


template

Basket<_Cl, _T_prio>::Basket(const Basket &basket) {

    size = basket.getsize();

    if(size == 0u) {

        storage = NULL;

        priorities = NULL;

    }

    else {

        for(unsigned int i=0; i
            storage[i] = basket.storage[i];

        }

        for(unsigned int i=0; i
            priorities[i] = basket.priorities[i];

        }

    }

    std::clog << "Basket copy constructor" << std::endl;

}


template

Basket<_Cl, _T_prio>::~Basket() {

    delete[] storage;

    delete[] priorities;

    std::clog << "Basket destructor" << std::endl;

}


template

Basket<_Cl, _T_prio>& Basket<_Cl, _T_prio>::operator=(const Basket<_Cl, _T_prio> &basket) {

    if(storage != NULL) {

        delete[] storage;

    }

    if(priorities != NULL) {

        delete[] priorities;

    }

    size = basket.getsize();

    if(size == 0u) {

        storage = NULL;

        priorities = NULL;

    }

    else {

        for(unsigned int i=0; i
            storage[i] = basket.storage[i];

        }

        for(unsigned int i=0; i
            priorities[i] = basket.priorities[i];

        }

    }

    std::clog << "Basket operator=" << std::endl;

    return *this;

}


template

unsigned int Basket<_Cl, _T_prio>::getsize() const {

    return size;

}


#endif // BASE_BASKET_HPP

basket.hpp:

#ifndef BASKET_HPP

#define BASKET_HPP


#include "base_basket.hpp"

#include


template

class Priority_Basket : public Basket<_Cl, _T_prio> {

    protected:

        virtual bool isgreater(unsigned int &i, unsigned int &j) const {

            return priorities[i] > priorities[j];

        }

    public:

        Priority_Basket() : Basket<_Cl, _T_prio>() {

            std::clog << "Priority_Basket default constructor" << std::endl;

        }

        Priority_Basket(const unsigned int &size) : Basket<_Cl, _T_prio>(size) {

            std::clog << "Priority_Basket size constructor" << std::endl;

        }

        Priority_Basket(const Priority_Basket &basket) : Basket<_Cl, _T_prio>(basket) {

            std::clog << "Priority_Basket copy constructor" << std::endl;

        }

};


#endif // BASKET_HPP

main.cpp:

#include "basket.hpp"


int main() {

    Priority_Basket a(5u);

    Priority_Basket b(a);

    return 0;

}

Makefile:

SHELL = /bin/sh

CXX = g++

.SUFFIXES:

.SUFFIXES: .cpp .hpp .o


OBJS = main.o

EXE = main

PEDANT = -ansi -pedantic

WARN = -Wall -Wextra $(PEDANT)


#debug

CXXFLAGS = $(WARN) -c -ggdb

CXXLINK = $(WARN)


#release 

#CXXFLAGS = $(WARN) -c -O2 -DNDEBUG

#CXXLINK = $(WARN) -s


all: $(EXE)


$(EXE): $(OBJS)

	$(CXX) $(CXXLINK) $(OBJS) -o $(EXE)


main.o: main.cpp basket.hpp

	$(CXX) $(CXXFLAGS) main.cpp


.PHONY: clean basket.hpp

clean:

	rm -f $(OBJS) $(EXE)


basket.hpp: base_basket.hpp

Kilka słów wyjaśnienia: W pliku base_basket.hpp jest klasa Basket, w której jest wirtualna funkcja isgreater. W pliku basket.hpp jest klasa Priority_Basket, która dziedziczy klasę Basket i implementuje funkcję isgreater. Wewnątrz implementacji isgreater w klasie Priority_Basket odwołuje się do zmiennych protected z klasy Basket. Kompilacja:

etam@etam-laptop:~/koszyk> make

g++ -Wall -Wextra -ansi -pedantic -c -ggdb main.cpp

In file included from main.cpp:6:

basket.hpp: In member function ‘virtual bool Priority_Basket<_Cl, _T_prio>::isgreater(unsigned int&, unsigned int&) const’:

basket.hpp:12: error: ‘priorities’ was not declared in this scope

make: *** [main.o] Błąd 1

Żeby było ciekawiej po usunięciu template wszystko ładnie się kompiluje i działa,

wszystkie:

template

zamien na:

template

Zamiast priorities użyj this->priorities.

Wyjaśnienie: http://www.parashift.com/c+±faq-lite/templates.html#faq-35.19

To akurat nie pomoże, ponieważ priorities jest zależne od parametrów wzorca.

A mnie pomogło :^o

Wystarczy, że podmienisz zawartość basket.hpp (różnica występuje tylko w jednej linii):

basket.hpp:

#ifndef BASKET_HPP

#define BASKET_HPP


#include "base_basket.hpp"

#include


template

class Priority_Basket : public Basket<_Cl, _T_prio> {

protected:

  virtual bool isgreater(unsigned int &i, unsigned int &j) const {

    return this->priorities[i] > this->priorities[j];

  }

public:

  Priority_Basket() : Basket<_Cl, _T_prio>() {

    std::clog << "Priority_Basket default constructor" << std::endl;

  }

  Priority_Basket(const unsigned int &size) : Basket<_Cl, _T_prio>(size) {

    std::clog << "Priority_Basket size constructor" << std::endl;

  }

  Priority_Basket(const Priority_Basket &basket) : Basket<_Cl, _T_prio>(basket) {

    std::clog << "Priority_Basket copy constructor" << std::endl;

  }

};


#endif // BASKET_HPP

To na pewno nie działa. Kompilator wywala, że “= int” tylko przy klasie.

Dzięki! Działa :smiley: