Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Cast to derived class?

Reply
Thread Tools

Cast to derived class?

 
 
christian.pontesegger@googlemail.com
Guest
Posts: n/a
 
      11-12-2007
Hi all,

lately I had a problem where I wanted to cast a basic class to a
derived type, which did not introduce any new members and did not
change any stuff with dynamically allocated memory. I just wanted to
add some methods to the class.

So my question is:
Is it valid C++ to create a basic class and to cast it to a derived
one the way I did in my example below? The example works fine for
MinGW, but I'm not sure if this is ABI dependent.

Example code:

<code>

#include <stdio.h>

class Basic {

public:
Basic(int a, int b) {
a_ = a;
b_ = b;
};

int getA() {
return a_;
};
int getB() {
return b_;
};

private:
int a_, b_;
};

class Derived : Basic {

public:
Derived(int a, int b) : Basic(a, b) {}
;

int multiply() {
return getA() * getB();
};
};


int main() {
Basic *basic = new Basic(2, 4);

Derived *derived = (Derived *)basic;
printf("%d * %d = %d\n", basic->getA(), basic->getB(), derived-
>multiply());


delete basic;

return 0;
}

</code>

 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-12-2007
* http://www.velocityreviews.com/forums/(E-Mail Removed):
> Hi all,
>
> lately I had a problem where I wanted to cast a basic class to a
> derived type, which did not introduce any new members and did not
> change any stuff with dynamically allocated memory. I just wanted to
> add some methods to the class.
>
> So my question is:
> Is it valid C++ to create a basic class and to cast it to a derived
> one the way I did in my example below?


No, it's Undefined Behavior.


> Example code:
>
> <code>
>
> #include <stdio.h>
>
> class Basic {
>
> public:
> Basic(int a, int b) {
> a_ = a;
> b_ = b;
> };
>
> int getA() {
> return a_;
> };


The prefix "get" serves no useful purpose. It just clutters the code
and incorrectly indicates some dynamic action to obtain the value.


> int getB() {
> return b_;
> };
>
> private:
> int a_, b_;
> };
>
> class Derived : Basic {
>
> public:
> Derived(int a, int b) : Basic(a, b) {}
> ;
>
> int multiply() {
> return getA() * getB();
> };
> };
>
>
> int main() {
> Basic *basic = new Basic(2, 4);
>
> Derived *derived = (Derived *)basic;
> printf("%d * %d = %d\n", basic->getA(), basic->getB(), derived-
>> multiply());

>
> delete basic;
>
> return 0;
> }
>
> </code>


All you're achieving is the member function notation, and that's far too
little to justify using implementation specific behavior.

Instead, in this particular case, define

int productOver( Base const& x ) { return x.a()*x.b(); }

Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
 
 
 
Juha Nieminen
Guest
Posts: n/a
 
      11-12-2007
Alf P. Steinbach wrote:
>> int getA() {
>> return a_;
>> };

>
> The prefix "get" serves no useful purpose. It just clutters the code
> and incorrectly indicates some dynamic action to obtain the value.


What kind of strange principle is that?

So what if it "incorrectly indicates some dynamic action"? It's a
public interface. You *don't know* what it does inside. You *don't care*
what it does inside. It could perform an SQL database search for all you
know. The only thing you care is what it's defined to do, ie. it returns
a specified value, and that's it.

"get<something>()" is a perfectly valid and good member function name.
It's descriptive and concise, and above all, it's abstract. It hides the
actual implementation, which is good.

If it was somehow named after what it actually does (eg. simply
returns a member variable), then what happens if in the future its
implementation is changed to something else? Are you going to change the
name of the function to reflect that?
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-12-2007
* Juha Nieminen:
> Alf P. Steinbach wrote:
>>> int getA() {
>>> return a_;
>>> };

>> The prefix "get" serves no useful purpose. It just clutters the code
>> and incorrectly indicates some dynamic action to obtain the value.

>
> What kind of strange principle is that?
>
> So what if it "incorrectly indicates some dynamic action"? It's a
> public interface. You *don't know* what it does inside. You *don't care*
> what it does inside. It could perform an SQL database search for all you
> know. The only thing you care is what it's defined to do, ie. it returns
> a specified value, and that's it.
>
> "get<something>()" is a perfectly valid and good member function name.
> It's descriptive and concise, and above all, it's abstract. It hides the
> actual implementation, which is good.
>
> If it was somehow named after what it actually does (eg. simply
> returns a member variable), then what happens if in the future its
> implementation is changed to something else? Are you going to change the
> name of the function to reflect that?


getSomething is technically valid but not good: it's ungood.

It is a Java'ism. In Java it serves a technical purpose for the kind of
name you applied it to. In C++ it does not.

Compare

getSin(v)*getX()

to

sin(v)*x().

"Get" it?

Probably not -- you'll get it long after this, and then wonder about
what you could have been thinking earlier -- but anyway, also consider

void getLargeDataSet( std::vector<double>& v ) { ... }

// Wrapper for ease of use, relying on RVO.
std::vector<double> largeDataSet()
{
std::vector<double> result;
getLargeDataSet( result );
return result;
}

where the two name forms play different roles. If you use "get"
indiscriminately for a completely (worse than) useless purpose, as you
did, you lose the ability to use "get" for something useful, as above.


Cheers, & hth.,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
Kira Yamato
Guest
Posts: n/a
 
      11-12-2007
On 2007-11-12 13:30:28 -0500, "Alf P. Steinbach" <(E-Mail Removed)> said:

> * Juha Nieminen:
>> Alf P. Steinbach wrote:
>>>> int getA() {
>>>> return a_;
>>>> };
>>> The prefix "get" serves no useful purpose. It just clutters the code
>>> and incorrectly indicates some dynamic action to obtain the value.

>>
>> What kind of strange principle is that?
>>
>> So what if it "incorrectly indicates some dynamic action"? It's a
>> public interface. You *don't know* what it does inside. You *don't care*
>> what it does inside. It could perform an SQL database search for all you
>> know. The only thing you care is what it's defined to do, ie. it returns
>> a specified value, and that's it.
>>
>> "get<something>()" is a perfectly valid and good member function name.
>> It's descriptive and concise, and above all, it's abstract. It hides the
>> actual implementation, which is good.
>>
>> If it was somehow named after what it actually does (eg. simply
>> returns a member variable), then what happens if in the future its
>> implementation is changed to something else? Are you going to change the
>> name of the function to reflect that?

>
> getSomething is technically valid but not good: it's ungood.
>
> It is a Java'ism. In Java it serves a technical purpose for the kind
> of name you applied it to. In C++ it does not.
>
> Compare
>
> getSin(v)*getX()
>
> to
>
> sin(v)*x().
>
> "Get" it?


I think I.get_it(). Oh wait, I meant to say I.it(). Hmm... That
doesn't look right.

In the case of sine, sine is really a function object. The () operator
is overloaded to mean "evaluate this function at". So, the verb
'evaluate' is implied here. To be verbose, it should've been
sine.evaluate(v).
This implied verb 'evaluate' is acceptable here because this is a
widely accepted mathematical notation. For other stuff, I do prefer to
use a verb form to state what my methods are doing.

>
> Probably not -- you'll get it long after this, and then wonder about
> what you could have been thinking earlier -- but anyway, also consider
>
> void getLargeDataSet( std::vector<double>& v ) { ... }
>
> // Wrapper for ease of use, relying on RVO.
> std::vector<double> largeDataSet()
> {
> std::vector<double> result;
> getLargeDataSet( result );
> return result;
> }


Why not just declare class for the noun 'LargeDataSet' and use the verb
'getLargeDataSet' for the function instead?

>
> where the two name forms play different roles. If you use "get"
> indiscriminately for a completely (worse than) useless purpose, as you
> did, you lose the ability to use "get" for something useful, as above.


--

-kira

 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-13-2007
* Kira Yamato:
> On 2007-11-12 13:30:28 -0500, "Alf P. Steinbach" <(E-Mail Removed)> said:
>
>> * Juha Nieminen:
>>> Alf P. Steinbach wrote:
>>>>> int getA() {
>>>>> return a_;
>>>>> };
>>>> The prefix "get" serves no useful purpose. It just clutters the code
>>>> and incorrectly indicates some dynamic action to obtain the value.
>>>
>>> What kind of strange principle is that?
>>>
>>> So what if it "incorrectly indicates some dynamic action"? It's a
>>> public interface. You *don't know* what it does inside. You *don't care*
>>> what it does inside. It could perform an SQL database search for all you
>>> know. The only thing you care is what it's defined to do, ie. it returns
>>> a specified value, and that's it.
>>>
>>> "get<something>()" is a perfectly valid and good member function name.
>>> It's descriptive and concise, and above all, it's abstract. It hides the
>>> actual implementation, which is good.
>>>
>>> If it was somehow named after what it actually does (eg. simply
>>> returns a member variable), then what happens if in the future its
>>> implementation is changed to something else? Are you going to change the
>>> name of the function to reflect that?


Forgot to answer that, the answer is it depends, and it also depends
whether it's a good idea to expose implementation strategy via a name.
Say the original implementation was a simple lookup in a cache, whereas
the new one does a network database lookup to be Really Really Sure. In
that case, the new implementation isn't just a new implementation: code
that relied on the "essentially no cost" of the original will sputter
and die if the implementation is simply replaced with the new one. It's
a different function even if it (eventually) achieves the same result.
So what are you going to name it? The idea that it's "the same"
function is incorrect, based on an incorrect notion that the network
database lookup is a purely internal implementation detail: it's not.

When the naming obscures a detail that is essential to correct usage,
it's not clear, even if in isolation it might seem to be very clear.


>> getSomething is technically valid but not good: it's ungood.
>>
>> It is a Java'ism. In Java it serves a technical purpose for the kind
>> of name you applied it to. In C++ it does not.
>>
>> Compare
>>
>> getSin(v)*getX()
>>
>> to
>>
>> sin(v)*x().
>>
>> "Get" it?

>
> I think I.get_it(). Oh wait, I meant to say I.it(). Hmm... That
> doesn't look right.
>
> In the case of sine, sine is really a function object. The () operator
> is overloaded to mean "evaluate this function at". So, the verb
> 'evaluate' is implied here. To be verbose, it should've been
> sine.evaluate(v).


Yes, I think you got it -- that part at least.


> This implied verb 'evaluate' is acceptable here because this is a widely
> accepted mathematical notation. For other stuff, I do prefer to use a
> verb form to state what my methods are doing.


Well, so does Marshall Cline, the FAQ's author.

However, my own ideas in this area are based on "readable code", the
notion that code that can be read straightforwardly tends to be more
clear than otherwise. Of course, that was also the basic idea of COBOL,
so it can be implemented in ungood ways: I think it's necessary, but not
sufficient, for clarity. Adjunct to that idea is the notion of
/creating a language/ for the reader of the code, that the nouns and
verbs etc. introduced as names, should make sense, should be eminently
readable, in the context of code using those names in a natural way.

So one main guideline for naming is to consider the usage and in
particular the readability, reading code as almost-natural language, of
the client code. Consistency is then derived from that goal. I.e., in
choosing what to be consistent about in naming, the main thing to be
consistent about should IMO be that names yield readable, clear client
code, which requires intelligence and thus cannot currently be
completely formalized in fixed mechanical rules -- using only
mechanical rules for naming consistency may yield consistency at the
level of details, elevating those details to so great importance that
they become a real pain and great distraction, and in general yields
inconsistency at the level that counts, clarity.


>> Probably not -- you'll get it long after this, and then wonder about
>> what you could have been thinking earlier -- but anyway, also consider
>>
>> void getLargeDataSet( std::vector<double>& v ) { ... }
>>
>> // Wrapper for ease of use, relying on RVO.
>> std::vector<double> largeDataSet()
>> {
>> std::vector<double> result;
>> getLargeDataSet( result );
>> return result;
>> }

>
> Why not just declare class for the noun 'LargeDataSet' and use the verb
> 'getLargeDataSet' for the function instead?


The above gives the client code a choice:

* prematurely optimize execution time by using getLargeDataSet(),

which means introducing an unnecessary variable and writing successive
interacting statements instead of a single simple expression, or

* optimize programmer's time by using largeDataSet()

(no extra variable, expression-oriented code). In general, optimizing
programmer's time, when including in that future maintainance time, is
very very seldom premature. It should be the default.

And much of what goes on in C++ these days, including C++0x (hopefully
C++09), is all about achieving expression-oriented, readable, clear
code, optmizing programmer's time. That's not because of some abstract
high level ideal, but that practical experience over now about 25 years
has convinced the best & brightest that writing action-oriented
statements that interact via variables, leads to complexity, bugs and
much wasted programmer's time. Expressions are the new Great Thing(TM).


>> where the two name forms play different roles. If you use "get"
>> indiscriminately for a completely (worse than) useless purpose, as you
>> did, you lose the ability to use "get" for something useful, as above.


Cheers,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Derived Structure in Derived Class?? David C++ 3 01-29-2008 07:38 AM
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 01:44 PM
Derived::Derived(const Base&) developereo@hotmail.com C++ 4 05-23-2007 09:32 AM
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 12:07 AM
[RTTI] cast base class pointer to <templated> derived class pointer tirath C++ 3 10-12-2003 01:44 PM



Advertisments