C++ fundamentals I still have trouble with

Started by
20 comments, last by rip-off 15 years, 4 months ago
I'm having difficulty understanding a few keyword concepts. with const, what use can it have when it's put before a return type or a parameter? What does try/catch do, exactly? How does it differ from trying to catch an error with a simple condition? For that matter, some people use a '...' in some catch statements. What does that do? (The second part to this I am trying to Google, still would like to know concept though.) For what reason would someone want to make a do-nothing virtual destructor, or a few virtual functions when there are no classes to inherit them? (Both I have witnessed)
Advertisement
Quote:Original post by zyrolasting
with const, what use can it have when it's put before a return type or a parameter?


A const variable is a constant; it cannot be changed once initialized.

Quote:
What does try/catch do, exactly? How does it differ from trying to catch an error with a simple condition? For that matter, some people use a '...' in some catch statements. What does that do? (The second part to this I am trying to Google, still would like to know concept though.)


Try/catch blocks are used for exception handling. Basically, if you have a block of code that can throw an exception, wrap it in a try/catch block. What you put in the parenthesis of a catch() is the type of exception you want to catch, by putting (...), that catch block will handle anything that gets thrown.

Quote:
For what reason would someone want to make a do-nothing virtual destructor, or a few virtual functions when there are no classes to inherit them? (Both I have witnessed)


Base classes need virtual destructors to ensure that if an instance of a derived class is deleted from a base class pointer, the correct destructor will be called. Since default destructors are not virtual, you need to create an empty one.
Quote:Original post by zyrolasting
with const, what use can it have when it's put before a return type or a parameter?


If you pass or return a value, it's useless.
If you pass a reference, 'const' means that the function promises not to alter the referred-to thing via that reference.
If you return a reference 'const' requires that the caller not alter the referred-to thing via the returned reference. (Note that it's easy to assign the returned reference to a value, which thus makes a copy which the caller can modify, and modifications to which do not affect what the function referred to.)

Quote:What does try/catch do, exactly? How does it differ from trying to catch an error with a simple condition?


I don't know what you think you mean here, given that you use "try" and "catch" in your description of the alternative to try/catch. o_O Show some code.

Quote:For that matter, some people use a '...' in some catch statements. What does that do? (The second part to this I am trying to Google, still would like to know concept though.)


Good luck with Googling that kind of thing; Google tends to ignore punctuation. :)

When you 'catch', you must specify what kind of thing to catch. It's usual to throw (and therefore catch) instances of classes (i.e. objects), but it's legal to throw any kind of data - including ints, string literals etc. There's no description that really covers any of those types, so C++ allows you to write "catch (...)" to mean catch anything. Of course, this means that you don't get to inspect the caught value, because you don't know what type it is, and it doesn't have a name.

Quote:For what reason would someone want to make a do-nothing virtual destructor


When 'delete' is called on a base class pointer, the destructor is called. This is not fundamentally different from a normal function call: if the base class function is 'virtual', then dynamic dispatch is done; otherwise, the base class version of the function is used regardless.

If the function were not 'virtual', then the base class destructor would be called even if the pointer actually pointed at an instance of the derived class. This leads to undefined behaviour, technically. (In practice, it usually only results in memory leaks, if anything; but it costs nothing to get it right, because the compiler is very good at optimizing out do-nothing functions.)

Quote:or a few virtual functions when there are no classes to inherit them? (Both I have witnessed)


There might not be such classes yet, but they might be planned for. Or maybe they simply weren't shown to you. It's also possible that the programmer was making a premature generalization. It's hard to say without seeing an actual example.
Quote:Original post by Zahlman
Quote:Original post by zyrolasting
with const, what use can it have when it's put before a return type or a parameter?


If you pass or return a value, it's useless.


Sometimes, returning a const value isn't completely useless. You can use it to stop people from doing things like ( foo + bar ) = baz; where foo overloads operator+ to return a constant value. Though, I admit, this is a very rare case, and is one of the very few reasons that you would want to return a constant value.

[size=1]Visit my website, rawrrawr.com

Quote:Original post by Zahlman
Quote:Original post by zyrolasting
with const, what use can it have when it's put before a return type or a parameter?

If you pass or return a value, it's useless.


I'm not sure I agree.

In general, you mark a parameter as const when you don't want it to be changed inside a function. Now, it's true that if the parameter was passed by value, changing it would not affect the original variable, but if the function should not change the parameter, it's still a logical error. Marking the parameter as const allows the compiler to catch these errors.
Quote:Original post by zyrolasting
with const, what use can it have when it's put before a return type or a parameter?


It can be useful when enforcing proper use of you created types. Let say you overloaded the * operator;

Widget operator*(const Widget& lhs, const Widget& rhs){ //Stuff}


With the above code, something like this will compile;

Widget a,b,c;//Do stuff//...a * b = c;


Not sure why you'd want to make an assignment to the product of two types. But its easily done by mistake.

if( a*b = c ) //Oh dear meant '=='


Defining the operator with a const return type will stop that compiling.

const Widget operator*(const Widget& lhs, const Widget& rhs){ //Stuff}


Most of the above was summerised from 'Effective C++' by Scott Meyers. It might be a good read for you if want some more insight into how to use c++ better.
Quote:Original post by bobofjoe
Sometimes, returning a const value isn't completely useless. You can use it to stop people from doing things like ( foo + bar ) = baz; where foo overloads operator+ to return a constant value. Though, I admit, this is a very rare case, and is one of the very few reasons that you would want to return a constant value.


I'm pretty sure that's already made illegal by the fact of returning a value instead of a reference. But others seem to disagree about this, so I may need to do some more research. :)

Quote:Original post by Gage64
I'm not sure I agree.

In general, you mark a parameter as const when you don't want it to be changed inside a function. Now, it's true that if the parameter was passed by value, changing it would not affect the original variable, but if the function should not change the parameter, it's still a logical error. Marking the parameter as const allows the compiler to catch these errors.


This is a more reasonable objection, but I'm not convinced that it would catch very much. For that matter, the decision that a passed-by-value parameter shouldn't be changed strikes me as kind of arbitrary - if it doesn't matter for correctness (and since we're making a copy, how can it?), it's just tying the implementor's hands.
Quote:
I'm pretty sure that's already made illegal by the fact of returning a value instead of a reference. But others seem to disagree about this, so I may need to do some more research. :)


It appears that the rules are different for built-in types and user-defined types:

class A{};A foo() { return A(); }int bar() { return 1; }int main(){    foo() = A();    bar() = 0;}

"ComeauTest.c", line 11: error: expression must be a modifiable lvalue      bar() = 0;      ^1 error detected in the compilation of "ComeauTest.c".

Not a word about foo() = A();
Quote:Original post by Zahlman
I'm pretty sure that's already made illegal by the fact of returning a value instead of a reference. But others seem to disagree about this, so I may need to do some more research. :)

The standardese for it is a little complicated. The return value of a function, whether it returns a primitive or a class type is an rvalue. However, if it is a non-const rvalue, you can call non-const member functions on it; this includes overloaded operators, since they are just syntactic sugar for the function call. All class types have automagically generated member functions if they aren't created by the user: operator= is one of them. Therefore, when you have:
A foo();foo() = A();

The compiler transforms the assignment to the member function call:
foo().operator=(A());

If foo() returned a primitive, foo() = something would fail to compile since operator= for a primitive type is not a function call, so the left hand side of the assignment needs to be an lvalue.
Thanks for the first few replies guys, they were helpful. I kind of zoned out when you went to your own separate debate, but I think I got the jist of it.

I am still curious about one more use of const. I came across a function that had const after the function name and return type, but before the parameter list.

float foo const ();

I thought this was especially strange, (and even a syntax error), but it ran.
What can this positioning of the keyword accomplish?

This topic is closed to new replies.

Advertisement