| Bourgond Aries (12) | |||||||
|
Good day helpful forumers... I have a problem, and I will explain what I imply to do with WORKING code, and then I will provide segfaulting code. Working code:
Very well, let's try the same with virtually inherited B:
The debugger (gdb) doesn't make me any wiser; the call stack is merely main. The segfault occurs on the reinterpret_cast. So what do I need to do to fix this issue? (The issue of setting data in a block of memory that contains virtually inherited data in its classes) | |||||||
|
Last edited on
|
|||||||
| Peter87 (3910) | |
| What I think happens is that when you use virtual inheritance it will have to use a vtable to lookup the location of b, but the vtable pointer will not be initialized until the A constructor has been called. | |
|
|
|
| L B (3806) | |
|
Why are you trying to do this? Semantics of inheritance and polymorphism are implementation defined, most likely you're breaking stuff. I don't think casting to A* like that will ever work. EDIT: Yeah, as Peter said above, your implementation probably tries to use the VTABLE, which is garbage values. operator new will work instead of using that plain buffer. | |
|
Last edited on
|
|
| Bourgond Aries (12) | ||||
|
L B - How are they implementation defined? Aren't they standard C++? Also casting to A* works when there is non-virtual inheritance and you can set pretty much any data member of the buffer. Just try it out! Why am I trying to do this? Because I plan on building an inheritance chain, and I want to simply virtually inherit a single class into all members of the chain, and initialize this data before the object lowest in the chain is created. I simply want to avoid having to send (and copy) data through constructors, making for ugly and slow programming. Peter87 - Yes that seems to be the case, so I guess I'll need to do things manually:
Edit: in response to L B - Is there any possible way to explicity initialize the vtable before object creation so that I can dereference some data? | ||||
|
Last edited on
|
||||
| L B (3806) | |
|
@OP I tried some hacks for you but they didn't work. I was hoping B would be constructed before C, but apparently the VTABLE is still unuseable at this point. http://ideone.com/jOTIBj @Bourgond Aries: The way a compiler implements the semantics of polymorphism and virtual inheritance is implementation defined and means you cannot reliable mess with memory like that. | |
|
|
|
| Bourgond Aries (12) | |
|
Bourgond Aries = OP xD So it seems that the argument list has to be finished before the vtable becomes usable? | |
|
|
|
| L B (3806) | |
|
OP = Original Post OPer = Original PostER So unless you are a post... And I don't know, it's implementation-defined. And that means that this: *reinterpret_cast<int *>(buffer + 8) = 15;Will not work for all compilers or all cases, because it won't always be off by 8. Also, what if B has its own constructor? ;p | |
|
Last edited on
|
|
| TheIdeasMan (1753) | ||
Bourgond Aries wrote:
Why don't you just put the stuff you want to inherit in the base class? Then it will be inherited. Base classes are initialised first, and the initialisation descends the inheritance tree. Virtual inheritance is for helping when you have multiple inheritance (2 or more parent classes, as in the diamond problem). It looks like you only need public inheritance here. If you need to use casting, it is generally a sign that some thing is wrong with the design. | ||
|
|
||
| L B (3806) | |
| Also, if for some reason you can't change the base class, you can always extend it with another class, do whatever in there, and then have your lowest-down classes inherit that middle class. | |
|
|
|
| Bourgond Aries (12) | |||
|
L B - On the forums I've been to the definition of OP is interchangable xD If B has its own constructor (where it actually initializes data), then what has been changed externally is overwritten. TheIdeasMan - I think I haven't really specified what I meant with my design. Therefore I'll give you some code:
See how I need to isolate data? For putting it in a single base class would make it "global" to all the classes, and I want to avoid that. Also, the diamond problem occurs here with the data, and therefore I want virtual inheritance - To share what needs to be shared. L B can you provide some example of base class extension? I think I know what you mean but code is just so much more understandable :P | |||
|
Last edited on
|
|||
| L B (3806) | |
|
Why do you need to create the information from a buffer? I think you should consider passing the information you want to A's constructor, which passes it to the constructors of all its base classes. Also, you don't need to extend D and E in A because C does that for you, and since it is virtual inheritance, they are direct base classes anyway. | |
|
|
|
| Bourgond Aries (12) | |||
|
L B: - I want to initialize standard information because of the following problem: You have class A, B, C,..., Z. Chronological execution commences; but Z needs a variable A creates. What? You're gonna pass that variable all the time through every constructor? And when you need to add / delete do that for every constructor? My answer was to create new classes that inherit a map - this map can be sent at will (so classes that do not need to pass it on, do not need to get the map). Due to this being automatic; the programmer does not need to worry about editing all those constructors. Because there's a freedom of choosing whether to pass it on or not; you retain C++ freedom of choice. You don't pay for that what you do not use!
The static create function is there to create a first class object from a non-object. It also creates a new m_map. The build function then spreads this same map to a new class object that is created by a class that inherits from Vault. The thing is that in the inheritance chain; it would be nice if all classes could virtuall inherit from Vault, so that they're all initialized and can all work with their own piece of code without having to pass it through constructors. I hope this answers your question. Also, I know how virtual inheritance works, but it seems I'll just be stuck using non-virtual inheritance for the time being, and just acquiring the data from the map in the class that is created, and then sending that data through constructors to the virtually inherited classes... | |||
|
|
|||
| L B (3806) | |
| If you need to virtually inherit 26 classes you're doing something very wrong. I hope you find the solution, since I cannot offer one. | |
|
|
|
| TheIdeasMan (1753) | ||
|
@Bourgond Aries Perhaps you can give us your real life example of what you are trying to do, then we can possibly offer some insight into the design. Using a map to aid the design as well as casting & lots of code instead of normal class design seems weird IMO at this stage. You have some reasonably complex code, I am not sure whether you know all the following stuff thoroughly already, and I want to avoid providing junior advice to someone who knows much more than me. However, I don't see any clues that you are aware of them, so here goes .... To avoid the cast, why can't you have an interface in the base class and use that to initialise / retrieve it's members? I understand you only want inherit things some of the time - so this means you are contradicting the "IS A" relationship by having inheritance in this situation. Also, there is the "USES A " & "HAS A" relationships. There are other ways of doing things - like making use of the Composite Design pattern to build complex objects. This link provides an overview of all 23 of them:
I have just bought the "Gang of Four" book, which gives a much more detailed look. HTH | ||
|
|
||
| Bourgond Aries (12) | |||
|
L B: - Well I'll offer a real life solution, as TheIdeasMan suggested. TheIdeasMan: - Let me assure you that I [think i] know exactly what I'm doing with my code. I know what I want, and I'll now try to explain what that is: A system that makes programming larger systems easier; it must eliminate some of the most common C++ programming quirks that annoy me. (Yes, very ego-centric of me) First some key points in the design. 1. No dependencies on global variables allowed. - A: We create a map that is local to a chain of classes that have created each other and passed the data. Any class inheriting Vault will have access to a specific map that is shared with a few other classes that inherit Vault. Thus the "create" function comes in the playing field, it creates a new map and thus starts a new chain of data flow. 2. The ability to dynamically add or remove classes without too much work. - A: Imagine class A, B, C,... Z. Z requires data stores by A, but A is destroyed (deleted) when it builds B (through delete this;). A stores its item as a pointer in the map. Class X2 needs to be added, standard procedure would be to pass the map ("Global-local" data) through the constructors. This is extremely tedious and doesn't give me any breathing space. Therefore, we make every class inherit from Vault. Every class then uses a build function which automagically passes the map WITHOUT you doing anything but inherit from Vault! The map is accessible from any Vault-inheriting class (just like in parameter passing), that is actually "built" (build function) by a class that has a Vault. 3. Cohesion - A: The reinterpret casts are only performed to dereference map items. If a class Z needs to access data in A, then there will be coupling if Z knows through A what type the object needs to be. Luckily, we only need to reinterpret_cast once from the map's void ptr to Z's internal data pointer (which has a type). I put this in a templated protected member functions like so:
These functions are inherited by inheriting Vault, this means anything that doesn't inherit Vault has no access whatsoever to the map. Q: Why the heck do you use std::abs in a signed int map?! A: -1, -2,... contain system objects (Flare for signalling, object counter, mutexes..) 4. Allowing an inheritance chain to share the data as well: - A: Virtual inheritance, all object handle themselves yet they are intertwined. I really like that concept. Anywaysze,.. I've slept over the design and came up with using a proxy class. This solves my virtual inheritance problem whilst not having to pass object through constructors! I needed to change the create and build function. Proxy class definition is all the way down. (Post's too long, even tho it's under 8192 chars.) | |||
|
|
|||
| Bourgond Aries (12) | ||||
I left the Utility functions out on purpose, there are so many. I 'm nearing the char limit for a post so I'm gonna round it up;
One last thing; Made this some time ago, maybe it can help in explaining: http://mclo3.deviantart.com/art/Design-Patterns-Conveyor-Pattern-348272434 | ||||
|
Last edited on
|
||||