I need a way to do a cast without being returned a pointer to a new address but, the same address as the original.

Something like this:

derivedClass something_derived;

baseClass* basePointer = &something_dervived;

derivedClass* derivedPointer = static_cast <derivedClass*> (basePointer);

/* my problem is "derivedPointer" isnt assigned the same address as "basePointer".
I need a pointer back to type "derivedClass" to "basePointer"'s address */

Edited 4 Years Ago by James19142

Are you using multiple inheritance?

Off the top of my head I don't recall if the C++ standard requires the base and derived object address to be the same for single inheritance, but it simply cannot be for multiple inheritance. There's no way to organize the structure of the object to make that happen. If you're using single inheritance then my gut reaction is to say that the addresses are implementation-dependent and you can't depend on them being the same.

Are you trying to do something like this?

class base
{
public:
    base() {x = 0;}
protected:
    int x;
};

class derived : public base
{
public:
    derived() {x = 1;}
protected:
    int y;
};

void foo(base* b)
{
  derived* d = static_cast<derived*>(b); // <<<< this line
}

int main()
{
   derived d;
   foo(&d);
}

@Ancient Dragon
derived* d = static_cast<derived*>(b); // <<<< this line

i need d to point to the same address as b, but static_cast returned a new address when i used it

i need base* b = /*derived*/d; done backwards

I think you need to use dynamic_cast instead of static_cast. Read the requirements for derived_class here and here As indicated in the second link if you use virtual functions in base class you may not need casts at all.

Edited 4 Years Ago by Ancient Dragon

i need base* b = /*derived*/d; done backwards

That is exactly what the static_cast does. Why do you assume that doing base* b = d; makes it so that b contains the same address value as d. In fact, there is no guarantee that it will. In a single inheritance scheme, it might be reasonable to expect that the address value isn't going to change across the cast, but there is no specification or requirement that it must be so. This is implementation-defined.

When it comes to standard behavior, cast operators are pretty interesting because there is very little guarantee, and overall, the idea is that you should never really be concerned about what the actual addresses are. You could summarize the guarantees about pointer casts as follows:

  • When casting up or down a class hierarchy (base and derived classes), as long as the casts aren't ambiguous, the guarantee is that the pointer-value (address) will be correctly updated (by an offset, possibly a zero-offset) to make it point to what you want it to point to (the sub- or super-object of the type given in the cast expression). In other words, the observable behavior is well-defined, but the implementation (actual changes in address values) is not.
  • When casting from a class-pointer type to some integer type (or void*), then the only guarantee is that you can cast it back to the same class-pointer type and get the same address back again.

Essentially, anything else that you might speculate / test about how the addresses are updated across a cast is just speculation and is largely implementation-defined. And the above guidelines hold pretty much the same for all types of casts (static_cast, reinterpret_cast, dynamic_cast and const_cast), because the only real difference between these types of casts is what they are allowed to do, and how/when they check for validity (at compile-time, or at run-time (dynamic_cast)). The relevant sections of the standard are 5.2.7 to 5.2.11.

So, back to your question, if you have the following code:

derived d1;

base* b = &d1;      // implicit up-cast

derived* d2 = static_cast<derived*>(b);     // static down-cast.

The C++ standard (and all decent compilers) guarantee that (d2 == d1) is true, in other words, the casting back and forth is a perfectly reversible operation. In other words, here are the cases:

std::uintptr_t b_address = reinterpret_cast< std::uintptr_t >(b);
std::uintptr_t d1_address = reinterpret_cast< std::uintptr_t >(d1);
std::uintptr_t d2_address = reinterpret_cast< std::uintptr_t >(d2);

bool a1 = ( b_address == d1_address );   // UNSPECIFIED

bool a2 = ( b_address == d2_address );   // UNSPECIFIED

bool a3 = ( d1_address == d2_address );  // TRUE

bool a4 = ( d1 == reinterpret_cast< derived* >(d1_address) ); // TRUE

I hope you understand the logic here. C++ casting operators allow you to make any cast that makes sense, but no more. And that is done by leaving some intermediate steps with undefined resulting values. And don't go looking to solve your problems with C-style casts either, because C-style casts are just implemented in terms of whichever sequence of C++ casts works, which can result in weird non-portable behavior.

After reading the replies I redid the code and realized that all the C++ cast functions do exactly what I needed them to do in this case. I messed up in the pointer trail by grabbing an address from an array of similar name for the cast's parameter, and then noticed the change of addresses, my bad about that, should've revised my code before posting.

Edited 4 Years Ago by James19142

This question has already been answered. Start a new discussion instead.