Casting without casting?

Started by
10 comments, last by PureSnowX 11 years, 1 month ago

Hi

This may seems like a wierd question but is there a way to cast a base class upto a derived class (both is a pointer of the class ),

What I have is a derived class pointer that is inside a vector of baseclass pointers, my question is if I could get a derived class pointer from the vector without using

(c style casting)

dynamic_cast

static_cast

as I got the impression from people that those things are bad, if there are no standard way to do this, would it be better if I Included a "Copy return" function in my base class (and ovverirde it from the derived class) where I would have something like this pseudo code down here?


class Base
{
//Magical Code here and there

base* Copy(const BaseToCopy);



//Magical Code here and there
}

base* Base::Copy(const BaseToCopy)
{
Base newBase;
//Magical Copy code from BaseToCopy into the newBase
return &newBase
}

std::vector<std::shared_ptr<Base>> test;

DerivedClass* testDerived;

testDerived = test[0]->Copy(&test[0]); 

As this would theoretical work am not sure if this is a good way to do it or not, or if there exist a more so called "elegant" way to do it.

P.S

If I just should cast, which of the cast should I use if I know 100% for sure which class it is? or should always go safe with dynamic_cast?

Advertisement

What do you mean by "Those things are bad" ? Advice like that REQUIRES context. It is bad for condition x, but useful under condition y.

To cast to a derived class, use dynamic_cast<>.

But *USE IT PROPERLY*. That means only using it on objects that are the expected type, and being prepared to handle an exception if you use it improperly. If you use it improperly, or if you are in a poor design that forces you to potentially have exceptions, then yes you will have some performance penalties.

Note that what you describe is not generally done, and it usually means you have a bad design.

It is common to downcast (from a derived cast back to the base class) but uncommon to upcast (from the base class to a derived class).

One of the biggest benefits of inheritance hierarchies is that you can create an abstract base class, or interface, and program your systems against that. It provides virtual functions of everything that might change on subclasses. Then you can derive your subclasses and override whatever functionality you need.

If you find that you need to upcast it is a sign that you are likely missing some virtual functions, that your object is likely violating the SRP, that you are likely violating Dependency Inversion principles, and likely making other design mistakes.

With that in mind, what is the REAL problem that you are trying to solve with your 'copy' example?

I think a virtual constructor is what you're looking for...

What do you mean by "Those things are bad" ? Advice like that REQUIRES context. It is bad for condition x, but useful under condition y.

To cast to a derived class, use dynamic_cast<>.

But *USE IT PROPERLY*. That means only using it on objects that are the expected type, and being prepared to handle an exception if you use it improperly. If you use it improperly, or if you are in a poor design that forces you to potentially have exceptions, then yes you will have some performance penalties.

Note that what you describe is not generally done, and it usually means you have a bad design.

It is common to downcast (from a derived cast back to the base class) but uncommon to upcast (from the base class to a derived class).

One of the biggest benefits of inheritance hierarchies is that you can create an abstract base class, or interface, and program your systems against that. It provides virtual functions of everything that might change on subclasses. Then you can derive your subclasses and override whatever functionality you need.

If you find that you need to upcast it is a sign that you are likely missing some virtual functions, that your object is likely violating the SRP, that you are likely violating Dependency Inversion principles, and likely making other design mistakes.

With that in mind, what is the REAL problem that you are trying to solve with your 'copy' example?

Its not directly a problem where I can't use the code but, am trying to "polish"(not sure if the right word) my code.

Am currently doing a assigment, and I have just finish one of my sub goal and I want to clean up the code a little, and I noticed I have a tedence to cast alot both up and down, And I got a few comment saying I should try to cast less and to try to design it better. So I tried to find ways to get a derived pointer without casting somehow.

or other way to do it, what I could reach was either polluting my base class alot or to try to get the derived class.

One of the "problem" I have is that I cannot reach the derived class specific variables because its not the same ones from the base class.

P.S

the assigment is just a school assigment so we are pretty free to do it how we want to aslong it works

P.S.S

and the reason why I get the feeling why casting is bad would be cause of people I know seems to always get around similar of my problem without casting so I kinda have it in me thinking that says there probably a better way to do it.

I think a virtual constructor is what you're looking for...

This is actually something simlar to what I need for another problem! ty

And I got a few comment saying I should try to cast less and to try to design it better. So I tried to find ways to get a derived pointer without casting somehow.

To reiterate frob, and these others who are commenting on your code, you should check your design, not just try to find a way to cheat things by magically circumventing a cast. That you find yourself casting so much is a code smell, and you should really try to find a better approach. To repeat frob once more, what is it you are really trying to accomplish? Maybe we can help you find a better approach.

Hi
This may seems like a wierd question but is there a way to cast a base class upto a derived class (both is a pointer of the class ),
What I have is a derived class pointer that is inside a vector of baseclass pointers, my question is if I could get a derived class pointer from the vector without using
(c style casting)
dynamic_cast
static_cast
as I got the impression from people that those things are bad, if there are no standard way to do this, would it be better if I Included a "Copy return" function in my base class (and ovverirde it from the derived class) where I would have something like this pseudo code down here?


class Base
{
//Magical Code here and there

base* Copy(const BaseToCopy);



//Magical Code here and there
}

base* Base::Copy(const BaseToCopy)
{
Base newBase;
//Magical Copy code from BaseToCopy into the newBase
return &newBase
}

std::vector<std::shared_ptr<Base>> test;

DerivedClass* testDerived;

testDerived = test[0]->Copy(&test[0]); 
As this would theoretical work am not sure if this is a good way to do it or not, or if there exist a more so called "elegant" way to do it.



P.S
If I just should cast, which of the cast should I use if I know 100% for sure which class it is? or should always go safe with dynamic_cast?

Looks like you just need to pass your original Base class into your DerivedClass constructor:


class DerivedClass {
public:
    DerivedClass(shared_ptr<Base> createFromBase) {
        // do the copying from base
        // and additional things this Derived needs
    }
}


Then (with new C++ features):


auto testDerived = make_shared<DerivedClass>(test[0]); 


or (same thing):


shared_ptr<DerivedClass> testDerived(new DerivedClass(test[0])); 


If you want to manage pointers yourself (we call them sometimes naked pointers):


DerivedClass * testDerived = new DerivedClass(test[0]); 

// in this case you have to make sure to call
delete testDerived;
// exactly once if you want to free memory

You can also create derived class as a variable (this is allocaled on stack):


DerivedClass testDerived(test[0]);

But you must have in mind that variables are destroyed automatically as soon as they reach end of scope:


{
    DerivedClass testDerived(test[0]); // created

    // use it
} // <-- destroyed automatically

That's why you don't return pointers to local variables from functions:


DerivedClass * fun() {
    DerivedClass testDerived(test[0]); // created

    // use it just fine here

    return &testDerived; // <-- will return pointer to deleted variable
} // <-- destroyed automatically

However you can return pointer to your object if you allocate it on heap (with "new"):


DerivedClass * fun() {
    DerivedClass * testDerived = new DerivedClass(test[0]); // created

    return testDerived; // <-- will return pointer to heap object
}

However, you have to manage deletion yourself.
You can, however, wrap your new object into shared_ptr. Shared pointer calls "delete" on your object automatically as soon as there is no scope that uses it.


shared_ptr<DerivedClass> fun() {
    shared_ptr<DerivedClass> testDerived(new DerivedClass(test[0])); // created

    // use it

    return testDerived; // <-- will return copy of shared_ptr which manages pointer to your object
}

It is important not to mix shared pointers and naked pointers.
I hope I haven't got carried too far away with this post smile.png


Hi
This may seems like a wierd question but is there a way to cast a base class upto a derived class (both is a pointer of the class ),
What I have is a derived class pointer that is inside a vector of baseclass pointers, my question is if I could get a derived class pointer from the vector without using
(c style casting)
dynamic_cast
static_cast
as I got the impression from people that those things are bad, if there are no standard way to do this, would it be better if I Included a "Copy return" function in my base class (and ovverirde it from the derived class) where I would have something like this pseudo code down here?


class Base
{
//Magical Code here and there

base* Copy(const BaseToCopy);



//Magical Code here and there
}

base* Base::Copy(const BaseToCopy)
{
Base newBase;
//Magical Copy code from BaseToCopy into the newBase
return &newBase
}

std::vector<std::shared_ptr<Base>> test;

DerivedClass* testDerived;

testDerived = test[0]->Copy(&test[0]);
As this would theoretical work am not sure if this is a good way to do it or not, or if there exist a more so called "elegant" way to do it.



P.S
If I just should cast, which of the cast should I use if I know 100% for sure which class it is? or should always go safe with dynamic_cast?


Looks like you just need to pass your original Base class into your DerivedClass constructor:

class DerivedClass {
public:
    DerivedClass(shared_ptr<Base> createFromBase) {
        // do the copying from base
        // and additional things this Derived needs
    }
}

Then (with new C++ features):

auto testDerived = make_shared<DerivedClass>(test[0]);

or (same thing):

shared_ptr<DerivedClass> testDerived(new DerivedClass(test[0]));

If you want to manage pointers yourself (we call them sometimes naked pointers):

DerivedClass * testDerived = new DerivedClass(test[0]); 

// in this case you have to make sure to call
delete testDerived;
// exactly once if you want to free memory

You can also create derived class as a variable (this is allocaled on stack):

DerivedClass testDerived(test[0]);

But you must have in mind that variables are destroyed automatically as soon as they reach end of scope:

{
    DerivedClass testDerived(test[0]); // created

    // use it
} // <-- destroyed automatically

That's why you don't return pointers to local variables from functions:

DerivedClass * fun() {
    DerivedClass testDerived(test[0]); // created

    // use it just fine here

    return &testDerived; // <-- will return pointer to deleted variable
} // <-- destroyed automatically

However you can return pointer to your object if you allocate it on heap (with "new"):

DerivedClass * fun() {
    DerivedClass * testDerived = new DerivedClass(test[0]); // created

    return testDerived; // <-- will return pointer to heap object
}

However, you have to manage deletion yourself.
You can, however, wrap your new object into shared_ptr. Shared pointer calls "delete" on your object automatically as soon as there is no scope that uses it.

shared_ptr<DerivedClass> fun() {
    shared_ptr<DerivedClass> testDerived(new DerivedClass(test[0])); // created

    // use it

    return testDerived; // <-- will return copy of shared_ptr which manages pointer to your object
}

It is important not to mix shared pointers and naked pointers.
I hope I haven't got carried too far away with this post smile.png

I think you did. Passing a shared_ptr into a constructor is weird, and the rest, while sound advice, is off-topic.

Anyway, he isn't trying to copy the object but avoid a cast, and since we haven't seen the design it's difficult to advise on how to do that.

Hi
This may seems like a wierd question but is there a way to cast a base class upto a derived class (both is a pointer of the class ),
What I have is a derived class pointer that is inside a vector of baseclass pointers, my question is if I could get a derived class pointer from the vector without using
(c style casting)
dynamic_cast
static_cast
as I got the impression from people that those things are bad, if there are no standard way to do this, would it be better if I Included a "Copy return" function in my base class (and ovverirde it from the derived class) where I would have something like this pseudo code down here?


class Base
{
//Magical Code here and there

base* Copy(const BaseToCopy);



//Magical Code here and there
}

base* Base::Copy(const BaseToCopy)
{
Base newBase;
//Magical Copy code from BaseToCopy into the newBase
return &newBase
}

std::vector<std::shared_ptr<Base>> test;

DerivedClass* testDerived;

testDerived = test[0]->Copy(&test[0]); 
As this would theoretical work am not sure if this is a good way to do it or not, or if there exist a more so called "elegant" way to do it.



P.S
If I just should cast, which of the cast should I use if I know 100% for sure which class it is? or should always go safe with dynamic_cast?

Looks like you just need to pass your original Base class into your DerivedClass constructor:


class DerivedClass {
public:
    DerivedClass(shared_ptr<Base> createFromBase) {
        // do the copying from base
        // and additional things this Derived needs
    }
}


Then (with new C++ features):


auto testDerived = make_shared<DerivedClass>(test[0]); 


or (same thing):


shared_ptr<DerivedClass> testDerived(new DerivedClass(test[0])); 


If you want to manage pointers yourself (we call them sometimes naked pointers):


DerivedClass * testDerived = new DerivedClass(test[0]); 

// in this case you have to make sure to call
delete testDerived;
// exactly once if you want to free memory

You can also create derived class as a variable (this is allocaled on stack):


DerivedClass testDerived(test[0]);

But you must have in mind that variables are destroyed automatically as soon as they reach end of scope:


{
    DerivedClass testDerived(test[0]); // created

    // use it
} // <-- destroyed automatically

That's why you don't return pointers to local variables from functions:


DerivedClass * fun() {
    DerivedClass testDerived(test[0]); // created

    // use it just fine here

    return &testDerived; // <-- will return pointer to deleted variable
} // <-- destroyed automatically

However you can return pointer to your object if you allocate it on heap (with "new"):


DerivedClass * fun() {
    DerivedClass * testDerived = new DerivedClass(test[0]); // created

    return testDerived; // <-- will return pointer to heap object
}

However, you have to manage deletion yourself.
You can, however, wrap your new object into shared_ptr. Shared pointer calls "delete" on your object automatically as soon as there is no scope that uses it.


shared_ptr<DerivedClass> fun() {
    shared_ptr<DerivedClass> testDerived(new DerivedClass(test[0])); // created

    // use it

    return testDerived; // <-- will return copy of shared_ptr which manages pointer to your object
}

It is important not to mix shared pointers and naked pointers.
I hope I haven't got carried too far away with this post smile.png

Iam still pretty new so all tips and programming terms is welcome no matter how long the post is.


Hi
This may seems like a wierd question but is there a way to cast a base class upto a derived class (both is a pointer of the class ),
What I have is a derived class pointer that is inside a vector of baseclass pointers, my question is if I could get a derived class pointer from the vector without using
(c style casting)
dynamic_cast
static_cast
as I got the impression from people that those things are bad, if there are no standard way to do this, would it be better if I Included a "Copy return" function in my base class (and ovverirde it from the derived class) where I would have something like this pseudo code down here?


class Base
{
//Magical Code here and there

base* Copy(const BaseToCopy);



//Magical Code here and there
}

base* Base::Copy(const BaseToCopy)
{
Base newBase;
//Magical Copy code from BaseToCopy into the newBase
return &newBase
}

std::vector<std::shared_ptr<Base>> test;

DerivedClass* testDerived;

testDerived = test[0]->Copy(&test[0]);
As this would theoretical work am not sure if this is a good way to do it or not, or if there exist a more so called "elegant" way to do it.



P.S
If I just should cast, which of the cast should I use if I know 100% for sure which class it is? or should always go safe with dynamic_cast?


Looks like you just need to pass your original Base class into your DerivedClass constructor:

class DerivedClass {
public:
    DerivedClass(shared_ptr<Base> createFromBase) {
        // do the copying from base
        // and additional things this Derived needs
    }
}

Then (with new C++ features):

auto testDerived = make_shared<DerivedClass>(test[0]);

or (same thing):

shared_ptr<DerivedClass> testDerived(new DerivedClass(test[0]));

If you want to manage pointers yourself (we call them sometimes naked pointers):

DerivedClass * testDerived = new DerivedClass(test[0]); 

// in this case you have to make sure to call
delete testDerived;
// exactly once if you want to free memory

You can also create derived class as a variable (this is allocaled on stack):

DerivedClass testDerived(test[0]);

But you must have in mind that variables are destroyed automatically as soon as they reach end of scope:

{
    DerivedClass testDerived(test[0]); // created

    // use it
} // <-- destroyed automatically

That's why you don't return pointers to local variables from functions:

DerivedClass * fun() {
    DerivedClass testDerived(test[0]); // created

    // use it just fine here

    return &testDerived; // <-- will return pointer to deleted variable
} // <-- destroyed automatically

However you can return pointer to your object if you allocate it on heap (with "new"):

DerivedClass * fun() {
    DerivedClass * testDerived = new DerivedClass(test[0]); // created

    return testDerived; // <-- will return pointer to heap object
}

However, you have to manage deletion yourself.
You can, however, wrap your new object into shared_ptr. Shared pointer calls "delete" on your object automatically as soon as there is no scope that uses it.

shared_ptr<DerivedClass> fun() {
    shared_ptr<DerivedClass> testDerived(new DerivedClass(test[0])); // created

    // use it

    return testDerived; // <-- will return copy of shared_ptr which manages pointer to your object
}

It is important not to mix shared pointers and naked pointers.
I hope I haven't got carried too far away with this post smile.png

I think you did. Passing a shared_ptr into a constructor is weird, and the rest, while sound advice, is off-topic.

Anyway, he isn't trying to copy the object but avoid a cast, and since we haven't seen the design it's difficult to advise on how to do that.

What I tried to was to design a simple component-ish system, I simply had each component derived from the same base component and put it in a base component list, And from time to time I need to access the component from the object holding them so I just use the map.find("ComponentName").get(); and cast it into the correct component.

This is my class that holds the component and how I would acess it.



List<shared_ptr<Entity>> vEntityTotal;

TrasnformComponent* tc;
tc = (TrasnformComponent*)vEntityTotal[0]->ComponentList.find("TransformComponent")->second.get()
class Entity
{
public:
Entity(){}
~Entity(){}
std::string name;
std::string tag;
std::map<std::string,std::shared_ptr<BaseComponent>> ComponentList;
 
void AddComponent(std::shared_ptr<BaseComponent> type)
{
if(ComponentList.count(type->getTypeName()) == 0)
{
ComponentList.insert(std::make_pair(type->getTypeName(),type));
}
}
void Release();
};

But maybe I should just have a function that returns a copy of the component and I will just remove the component than reinsert the new one? that have been modified, not really sure how I should do it.

Casting is not so bad in this case. You have already asked for a TransformComponent so you know what type it is, and components are quite different from each other so you can't do everything from a common interface. I would however make the map private and put the cast into a templated GetComponent function to avoid the possibility of casting to the wrong type. If you do that, it should be safe enough without dynamic_cast.

Copying is not the right thing. It would be horribly inefficient.

The only real alternative to casting would be a message system, where the entity would pass on messages to the components. Maybe save that for the future because it's harder to set up.
The 2013 Inerbutts Olympics Committee has been notified concerning this thread. An entry is proposed for the category 'longest posts due to needless quoting'. Confirmation of eligibility should be available by the week's end.

Go for the gold, fellas.
void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

This topic is closed to new replies.

Advertisement