There is such a simple code:

#include <stdio.h> class B{ private: int j;//если у класса не будет переменных, то "this B" бует равен "this A" public: B(){ printf("this B=%d\n",(int)this); } }; class A:public virtual B{ public: A(){ printf("this A=%d\n",(int)this); } }; int main(){ A*a=new A(); delete a; } </code> 

Result of performance:

 this B=147431436 this A=147431432 

the result shows that this for class B is NOT the same as this for class A. If inheritance is NOT virtual, then the addresses will match. Also, if there are no parameters in class B, then the addresses will also match.

But now an example (with virtual inheritance and parameters) and addresses do not match. Is it possible to somehow get a pointer to object A from class B? those. it is necessary that class B explicitly knows the address of the entire instance, the successor of which it is

  • There is a little on this topic ru.wikibooks.org/wiki/%D0%A1%D0%B8%2B%2B in the section "Polymorphism and Multiple Inheritance" - alexlz
  • For what purpose do you need access to a child? Simply for such tasks it is more correct to use either a protected purely virtual method , or a “visitor” design pattern . - ߊߚߤߘ

2 answers 2

Is it possible to somehow get a pointer to object A from class B?

 A*a = dynamic_cast< A* >( this ); 

For non-polymorphic classes, it is suitable:

 A*a = static_cast< A* >( this ); 

only this call must be made after the declaration of class A , for example in cpp or inlin'ом , below the declaration of class A

those. it is necessary that class B explicitly knows the address of the entire instance, the successor of which it is

Ie, I understand correctly? You want to select from class B not just A , do you want to select from class B the farthest descendant - the root of the inheritance tree?

In the general case, this task is unsolvable by means of language: ancestors should not control the chain of descendants.

But, nevertheless, about 5-7 years ago, I did this. In a nutshell: a visual studio utility is being written that selects RTTI from all object files before the linking stage. Builds a chain of descendants for each compiled character:

 template< typename Base, typename Type > struct RTTI_Base{ static Base Type::**Offsets; static INT Count; }; 

Creates an additional section in such an object file, and substitutes addresses from it for each RTTI_Base< Base, Type >::Offsets .

RTTI_Base is like a request to this utility to get a chain of descendants from a given Type class that have a Base , i.e. spawned from some Base interface.

This is all certainly interesting, but, having played with such a post-compiler on different sets of classes, "threw it into the closet" as useless. In ordinary life, this is not necessary.

  • Here is the error: ../src/main.cpp:26:33: error: cannot dynamic_cast "this" (of type "class B * const") to type "class A *" (source type is not polymorphic) GCC compile 4.6.3 - caffeine
  • source type is not polymorphic - yes, this is a talking error. Indicates that A has no inheritance descriptors to which dynamic_cast oriented. Give these classes some virtual methods. For non-polymorphic classes, A a = static_cast <A> (this); - mega
  • In class B, the virtual method void test () = 0; in class A added virtual void test () = 0; as a result, A a = dynamic_cast <A> (this); compiles, but the variable "a" is zero - caffeine
  • Use static_cast , it is safer in this case. Most likely, your optimization ate polymorphism. - mega
  • Optimization off. Now wrote A a = static_cast <A> (this); in the end, this is the error: the conversion error of the base “B” to the derived type “A” through the virtual base type “B” - caffeine

I read it several times, but I still did not understand what was needed, and most importantly for what . It seems necessary to change the approach to the problem. By sabu comes to mind a trick with a strangely recurrent pattern (Curiously Reccuring Template Pattern)

 #include <iostream> using namespace std; //предполагаем что наследник будет передавать себя в качестве шаблона //таким образом знаем тип наследника template<class Child> class Base { public: void print() const { //не уверен в валидности static_cast static_cast<const Child*> (this)->printChild(); } }; class Derived: public Base<Derived> { public: void printChild() const { cout <<"Child"<<endl; } }; int main() { Derived* d = new Derived; d->print(); } 

The location of polymorphic objects in memory will help to understand what's happening with polymorphic types.

  • So here it is, this OOP! "And these people forbid me to pick my nose!" (c) Little Johnny. - alexlz