Home>

I have a question about pointers.

First, how are pointers of different types interpreted? ?

char qtr = 3289;
int * ptr =&qtr;


Suppose you have this code:
I think that an exception will be thrown for RISC CPUs because it spans alignment. I don't usually use it like this.

Char type address is assigned to int type pointer.
In this case, is ptr interpreted as aint pointer?Or is it achar pointer?

class Base {}
class Derived: public Base {}
Derived obj;
Base * ptr =&obj;


How about this one? This is a code I often see.Which pointer is ptr after all? ?

Second
I don't understand dynamic_cast.
The following is written in my book.

  

The real class type of the object pointed to by a pointer or reference is known only at runtime.

Eh? why? ?
In the above code example, you can see that Ptr contains a Derived type object without executing it. ?

void f (Base&base) {
   Derived&d = static_cast<Derived&>(base);// I don't know if base refers to derived.
}


In the function, it is certainly unknown whether it is referenced.
But ... you know the object you pass when you call the f function, even if it's not at runtime?

  

The real class type of the object pointed to by a pointer or reference is known only at runtime. Therefore, there is a possibility that the conversion always fails. Therefore, when using dynamic_cast, you must always write your code under the assumption that the conversion may fail.

N? ? What a hell it is.

Third, why is downcasting dangerous? ?
Convert basic pointer to derived pointer

You often see self-referenced pointers when creating linear lists.

typedef struct __node {
    int data;
    struct * __ node next;
} Node;

This is because pointers can be used even if they are incomplete.
The reason for this is that the pointer assigns an address and does not affect the value of the address, no matter what the structure is. (May be wrong.)

Think about this theory. I made a test code. It is appropriate.
The following code will compile. However, when compiling it comes out as Never Succeed.
Why? ?

struct Base {
    int member = 3489;
    void function () {
        std :: cout<<"Base :: funtion"<<std :: endl;
    }
    virtual void func () {
        std :: cout<<"Base :: virtual_func"<<std :: endl;
    }
};
class Derived final: public Base {
    public:
        int Derived_member = 3829;
        void function () {
            std :: cout<<"Derived :: function"<<std :: endl;
        }
        void func () {
            std :: cout<<"Derived :: virtual_func"<<std :: endl;
        }
};

Base base_obj;
Derived * derived_obj_ptr = dynamic_cast<Derived *>(&base_obj);


Take a look at the following code:
It is possible to assign an object of the base class to an object of the derived class.
On the other hand, derived class objects cannot be assigned to base class objects.

This means that the derived class may have a member variable that is not in the base class, so it cannot be copied.

(What is used at this time ... is a copy assignment operator? What happens when the base class object is on the right side ...)

class Base {...};
class Derived: public Base {...};
Base obj;
Derived obj2;
obj2 = obj;// ok!
obj = obj2 // ERROR !!


I know the object, but I don't know why the pointer is not.
Also, what are the conditions for downcasting?

The environment is Linux g ++.

c c++
  • Answer # 1

    Hello.

      

    If you have this code:

    It should be an error that a char pointer cannot be assigned to an int pointer.

      

    In this case, is ptr interpreted as an int pointer? Or is it a char pointer?

    int * ptr = reinterpret_cast<int *>(&qtr);
    That is, ptr is a pointer to int type.

      

    How about this? This is a code I often see. Which pointer is ptr interpreted after all? ?

    This is a little annoying. C ++ is strict on types as long as it is written normally.Base * ptr =&obj;'s ptr is declared as a pointer to the Base type, so what you assign is a pointer to the Base type.
    So it can be used with some sense of security.

    However, the pointed to is a Derived type object. Even if the point you are pointing to is treated as a Base type, there is no danger of undefined behavior.

      

    In the above code example, you can see that Ptr contains a Derived type object without executing it. ?

    That's certainly the code, but it's a "special case". Although it may be understood, generally it is correct to think that it is not understood.

    bool make_derived;
    std :: cin>>make_derived;
    Base * ptr = (make_derived)? New Derived: new Base;


    In such cases, you can only understand at runtime.

    Also assume that the function f () shown in the example is defined in foo.cpp and called from bar.cpp.
    The compiler when compiling foo.cpp doesn't have any information about bar.cpp, so it doesn't know what parameters are being called at compile time.
    This is often the case when foo.cpp is distributed as a library and someone who gets it calls it from bar.cpp.

    The code presented is dangerous if a Base type object is passed.
    In such cases, it is safe to use dynamic_cast<>and make sure that the result is not nullptr. (Note that converting a null pointer to a reference with*causes undefined behavior, so it must be handled with a pointer.)

    dynamic_cast<>is surprisingly slow so you can't afford to use it, but it's quite cumbersome to handle it without using it, so you can use it where speed is not required. (Some people deny downcasts themselves, but there are times when it is better to use them. Define virtual functions for all derived classes or avoid them if possible.)

      

    Third, why is downcasting dangerous? ?

    What do you see when you run the following source?
    It is dangerous because it causes undefined behavior.

    # include<iostream>
    struct Base
    {
        int x;
    };
    struct Derived: public Base
    {
        int y;
    };
    int main ()
    {
        Base b;
        b.x = 0;
        Derived * d_ptr = static_cast<Derived *>(&b);
        std :: cout<<d_ptr->y;
    }
      

    It is possible to assign a base class object to a derived class object.
      On the other hand, derived class objects cannot be assigned to base class objects.
      This means that the derived class may have a member variable that is not in the base class, so there is no way to copy it.

    Eh! It's completely the opposite.
    Derived classes can be assigned to base classes. And slicing may occur and cry.
    However, the reverse is prohibited by the compiler. I think this is because you can't set values ​​for variables that are only in derived classes.
    This can be done by defining an assignment operator or constructor that takes a const reference to the base class. This is because it should be set at the responsibility of the person who defined it.