C ++ inheritance. Changing Object Data Types

I am having problems forcing data type changes on my own objects. I have a base class: A and two classes derived from A , called B and C I pass objects B and C function that checks what type of object it is ( B or C ). Here is the sample code below and the question for my problem:

 enum ClassType {"B", "C"}; class A { protected: m_Type; public: ClassType Type() { return m_Type} ... ... }; class B : public A { otherMemberFunctions(); } class C : public A { otherMemberFunctions(); } void WhatType(vector<A*>* candidates){ vector<B*> b_candidates(0); vector<C*> c_candidates(0); for(int i = 0; i < candidates->size(); i++){ if(candidates->at(i)->Type() == B ){ B* b = (B*) candidates->at(i); b_candidates(b); } //Same idea for Object C } } 

Then I would use WhatType(vector<A*>* candidates) as follows

 vector<B*>* b_example WhatType((vector<A*>*) b_exmaple) 

When I populated the new vector b_candidates in the WhatType function. Will I have access to member functions in object B or will I only have access to member functions in base class A ?

I am confused about what happens to an object when I change the type of an object.

Here

 WhatType((vector<A*>*) b_exmaple) 

and here

 B* b = (B*) candidates->at(i); 
+2
source share
5 answers

When you get a pointer to a polymorphic object, you have two types: the "static" type of the object, which in your case will be A * and its "dynamic" or "real" type, which depends on what was actually assigned to it .

Dropping A * into B * forces the compiler to consider this pointer as a pointer to B ; it is safe if you really know that this pointer is actually a pointer to B , otherwise the compiler will start writing pointless code (calling methods B for data of a different type).

The checks you are trying to implement are the home version of RTTI, which is a mechanism that lets you know what a "real type" of a pointer is or a reference to a polymorphic class, and it moves safely around. Check out typeid and dynamic_cast in your C ++ manual for more information on this. (By the way, IIRC dynamic_cast designed not only for security in the event of an incorrect dynamic type, but also for your pointer, if you use it in complex class hierarchies, it can also perform additional magic, so avoid C-style casting for polymorphic classes)

By the way, in general, he believed that the "smell of code" should manually check the "real type" of the pointer in order to use it and use its methods: the ideal of OOP could only do work, although virtual methods are available in the base class.

A big warning: RTTI only works with polymorphic classes, that is, with classes that have at least one virtual method. On the other hand, if you are building a class hierarchy in which objects are passed as pointers to a base class, you will almost certainly want to create a virtual destructor, so that's okay.

+1
source

Since you added to B* , you will have access to B members.

+1
source

The actual type of objects does not change, of course, but if you only have a pointer (or reference) to the base class, you cannot access fields specific to subclasses.

What you can do to access the fields of a subclass is to use dynamic_cast to pass it to the subclass:

 A *a = new B; // We cant reach the members of class B in a B *b = dynamic_cast<B *>(a); // But now we have a proper pointer to B 
+1
source

So, if you had an object of type B created on the heap and held by a pointer of type A you can only see type A member functions to access the type B member functions that you have static_cast<B*> , which is ... "( B* )" ....

dynamic cast better since it will return a null if conversion is not possible. but of course this happens at runtime, so there is a penalty.

+1
source

Since B and C are À , a vector<B *> and vector<C *> contain A objects of the base class. If you decide to set your A::m_Type in your constructor, you will have no problems:

 enum ClassType {'B', 'C'}; // see I modified your definition class A { protected: ClassType m_Type; public: ClassType Type() { return m_Type}; ... ... }; class B : public A { public: B() : m_Type('B') {} .... }; 

Using this, you can easily check objects B and C After that, when you put the base objects in derivatives, you will get full access to their public methods and attributes.

-1
source

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


All Articles