There is a list of pointers to an abstract class. The list also contains pointers to the objects of the template class (of course inherited from the base abstract class). At the same time, I need to pull a function from the template class through a pointer to an abstract class, for which a type conversion is needed - and then the question is: is it possible to avoid specifying a template parameter when casting?

template <typename T> class A : public abst { ... fun(); } list<abst *> l; ... dynamic_cast<A *>(*l.begin()); // вот здесь 
  • fun - virtual, inherited from an abstract class? Or arbitrary specific class A ? - Harry
  • namely class A - if inherited, then there would be no need to cast the type - Andrej Levkovitch
  • In a sense, to specify the speaker-caste is unknown to what? By the way, in order to compile, you must add an asterisk in the last line to A; a *l.begin() is the same as l.front() . - bipll am
  • Then, as I understand it, you need to specify the type of the parameter - because which of the types would otherwise result in a pointer to the base type? The call must be unleashed at compile time, since it is not virtual ... - Harry
  • 2
    @AndrejLevkovitch why will she be there? Add another interface in which to write the fun () method, and cast to it - vegorov Sept

4 answers 4

An alternative is the Visitor template. However, it can be used only in the case of a limited number of heirs of the base class. And yes, if the case specified in the question is not the only one.

  • In other words, dynamic versus static, internal versus external, deepening versus expansion ... - bipll

It seems to me that the problem is not understanding what the template class for the compiler is. Those. nothing. After compiling the template class as such does not remain. There are only specializations (A, A, etc.) that were used in this particular program. I mean, the template type A does not exist as a full-fledged type. It can not lead to other types. Moreover, the base class (from which all template specializations are inherited) to A * cannot be cast.

PS This is my understanding of C ++ template classes, I can be wrong.

    In general, the most reasonable thing is in the @vegorov comment:

     class abst; struct has_fun: abst { virtual void fun() = 0; }; template<class T> struct A: has_fun { void fun(); }; list<abst *> l{new A}; has_fun *head = dynamic_cast<has_fun *>(l.front()); if(head) head->fun(); 
    • I meant multiple inheritance =) Type class A: public abst, public has_fun{... Truth of fact it almost does not change =) - vegorov
    • Well, yes, also an option, from left to right, they go or from top to bottom. - bipll

    Pointers always indicate the beginning of the object, and the beginning of the object for all heirs is the beginning of the object of the base class (the base class can have an array, structure, etc.) in its representation.

    Therefore, it is impossible to refer to the own methods of the heir object through the base class pointer. The base class has no idea how many and what heirs it may appear. This enables the independence of the already written code (classes) from the newly created ..

    If the base class is abstract, it’s best to simply call one of the virtual functions of the base class in your function. Then everything will be as you wish. For example:

     using namespace std; class abst { public: virtual ~abst() = default; virtual void f() = 0; }; template <typename T> class A : public abst { public: //... void fun() { cout << "show " << T() << endl; } void f() { fun(); } }; template <typename T> class B : public A<T> { public: void fun() { cout << "creat " << T() << endl; A<T>::fun(); cout << endl; } void f() { fun(); } }; struct Some_type { const string s; Some_type() : s("Some_type ") {} friend std::ostream& operator << (ostream& os, const Some_type& t) { os << ts; return os; } }; int main() { list<abst*> l; A<int> a; B<float> b; A<string> c; B<Some_type> d; d.fun(); l.push_back(&a); l.push_back(&b); l.push_back(&c); l.push_back(&d); for (const auto& p : l) // p->fun(); // так не можете p->f(); // только так return 0; } 

    And there is no need for a new inheritance ..

    • Pointers do not always indicate the beginning of a complete object. Enough to consider multiple inheritance. - AnT
    • The question was not about that at all. - Andrej Levkovitch 3:56 pm
    • right, not always ... I went over - AR Hovsepyan
    • @Andrej Levkovitch, you wanted to call the function of the heir through the pointer of the base class, but not create another base. I suggested in the function of the successor to call the virtual function of the base. What is the question then? ... - AR Hovsepyan
    • @ARHovsepyan you write that through the base type pointer you cannot refer to the heir, and I ask about casting the pointer type to the base class to a pointer to the heir. - Andrej Levkovitch 4:02 pm