C ++ - access to a method of a derived class through the interface pointer of the base class of the abstract template, without an explicit interface type

This is my first post. I spent hours checking the solution of the problem, referring to the link after the link to SO, but none of them described my problem (the closest I could get this and this ). So, let's work!

Description. I have to implement a set of specialized classes, each of which can store a linked list of its type. Also (the hard part), I have to implement the collection manager in such a way that adding more specialized classes to the collection does not affect its code.

Let me explain what I still have.

class IList {
    public:
    virtual IList& operator+( IList&) = 0;
    virtual void print() = 0;
    virtual int g_Size() const = 0;
//perfect till here

    virtual void Push(const int&) = 0;//needs to be upgraded
    virtual const int& operator[](int index) = 0;//needs to be upgraded
};

template<class T>
class Queue: public IList{
    //internal stuff
public:
    Queue();
    int g_Size() const;

    void print();

    void Push(const T& cv);

    const T& operator[](int index);

    ~Queue();
};//all implementation of Queue<T> is implemented and working, but removed for simplicity

class CIntList : public Queue<int>{
    //stuff here, specialized on int
};

class C_Manager{
    IList * classes[3];//notice the polymorphism, managing the class collection using a pointer to the common(base) interface
public:
    void testing()
    {
        for (int i = 0; i < 3; i++)
            classes[i] = new CIntList(i);
        classes[0]->Push(1); classes[0]->Push(2); classes[1]->Push(1121); classes[2]->Push(12);
        classes[0]->print();
        classes[2]->print();
        int a = classes[0]->operator[](1);
        classes[1]->Push(a + a);
    } //working fine
};

OK, so you may ask, what is the question ?

Push operator[] ( , ) . , , ,

class CFloatList: public Queue<float>
{
      //float stuff goes here
};

IList

class IList {
        public:
        virtual IList& operator+( IList&) = 0;
        virtual void print() = 0;
        virtual int g_Size() const = 0;
    //perfect till here

        virtual void Push(const int&) = 0;//used for int
        virtual const int& operator[](int index) = 0;//used for int

    //NEW DECLARATION FOR FLOAT
        virtual void Push(const float&) = 0;//used for float
        virtual const float& operator[](int index) = 0;//used for float

    };

? " ", ++.

?

, ++, , . !

# 1 ( jaggedSpire - , )

IList

class IList {
    public:
    virtual IList& operator+( IList&) = 0;
    virtual void afis() = 0;
    virtual int g_Size() const = 0;


    //templates
    template<typename T>
    void Push(const T& arg) //WORKS PERFECTLY
    {
        Queue<T>* cast = dynamic_cast<Queue<T>*>(this);
        cast->Push(arg);
    }
    template<typename T>
    const T& operator[](int index) //error
    {
        Queue<T>* cast = dynamic_cast<Queue<T>*>(this);
        return cast->operator[](index);
    }
};

void C_Manager::testing()

class C_Manager{
    public:
        void testing()
        {
            IList * a = new CIntList(1);
            a->Push(200);//WORKS PERFECTLY
            int c = a->operator[](0); //ERROR
        }
    };

Error   C2783   'const T &IList::operator [](int)': could not deduce template argument for 'T'

Error   C2672   'IList::operator []': no matching overloaded function found

intellisense: no instance of function template "IList::operator[]" matches the argument list

, , T- . , ?

+4
1

-, :

  • , IList
  • Queue<T> .
  • Queue<T>,
  • , void push const T& operator[], .
  • IList , , Queue<T> .

- : , , . , T Queue<T>, .

, ( , ), - , -. ++ , dynamic_cast

, ( ) -method ++.

, / - ++ . , , , : . , , . , , , .

T , , , Queue<T>.

, : dynamic_cast. , this , , .

: , . std::string , std::string, , , . , .

, . Parent, Child<T>, , T Child<T>, Parent:

class Parent{
    public:
    template <typename T>
    void foo(const T& t);

    virtual ~Parent(){}
};

template <typename T>
class Child : public Parent{

    public:
    void foo(const T& t);
};

// must be after the definition of the Child template, 
// because dynamic_cast requires a complete type to target
template <typename T>
void Parent::foo(const T& t){
    // throws on bad conversion like we want
    auto castThis = dynamic_cast<Child<T>&>(*this); 
    // if execution reaches this point, this is a Child<T>
    castThis.foo(t);
}

template<typename T>
void Child<T>::foo(const T& t){
    std::cout << typeid(T).name() << ": " << t << '\n';
}


int main(){
    Parent&& handle = Child<int>();

    try{
        handle.foo<int>(3);
        handle.foo<char>(0);
        handle.foo<std::string>("Hello!");
    }
    catch(std::bad_cast e){
        std::cout << "bad cast caught\n";
    }
}

g++ 5.2.0, clang 3.7

i: 3
bad cast caught

, .

, , . - std::vector<std::unique_ptr<Parent>> , .


, , :

  • . , - , . dynamic_cast , . std::bad_cast. .
  • - -, - , - name ++. :

    , , , . . .

, foo Child<T>, - Child<T>, Parent .
 3. , , .

+1

Source: https://habr.com/ru/post/1626062/


All Articles