Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Declare function in C++

114 views
Skip to first unread message

Tuấn Trần

unread,
Apr 13, 2016, 12:46:52 AM4/13/16
to
Hi,
I face a declaration function in C++ BUT I don't know what's this mean!
This is my code:
bool Check() const;

Can you explain this for me?
Thanks!

Wouter van Ooijen

unread,
Apr 13, 2016, 1:35:02 AM4/13/16
to
Op 13-Apr-16 om 6:46 AM schreef Tuấn Trần:
If you want to program in C++ and you don't understand what a function
declaration is or means than my conclusion is that you should read an
(introductory) book on C++ or even C.

If you con't know what a specific part of that declaration (for instance
the 'const') means you should ask a more specific question.

Wouter van Ooijen

Tuấn Trần

unread,
Apr 13, 2016, 4:31:31 AM4/13/16
to
Vào 12:35:02 UTC+7 Thứ Tư, ngày 13 tháng 4 năm 2016, Wouter van Ooijen đã viết:
Hi,
Yes, I don't know what 'const' mean in declaration!

Robert Wessel

unread,
Apr 13, 2016, 4:51:21 AM4/13/16
to
Assuming that's a member function, it declares a const member
function, which cannot alter any non-static or non-mutable data
members in the class. It allows the (const) member function to be
called on a const instance of the class (since the const member
function cannot modify - with the exceptions noted above - the class).

This is a C++11 feature.

Juha Nieminen

unread,
Apr 13, 2016, 6:20:50 AM4/13/16
to
What do you mean it's a C++11 feature?

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Paavo Helde

unread,
Apr 13, 2016, 8:20:01 AM4/13/16
to
According to
https://www.usenix.org/legacy/publications/compsystems/1989/sum_stroustrup.pdf
, const member functions were defined and implemented in August 1985.




Paavo Helde

unread,
Apr 13, 2016, 8:32:31 AM4/13/16
to
On 13.04.2016 15:19, Paavo Helde wrote:
> According to
> https://www.usenix.org/legacy/publications/compsystems/1989/sum_stroustrup.pdf
> , const member functions were defined and implemented in August 1985.

Oops sorry, more careful reading says it was later than August 1985,
sometime in 1985-1989.


Öö Tiib

unread,
Apr 13, 2016, 11:58:04 AM4/13/16
to
What do you mean by "cannot modify the class"?

Daniel

unread,
Apr 13, 2016, 12:14:03 PM4/13/16
to
On Wednesday, April 13, 2016 at 4:51:21 AM UTC-4, robert...@yahoo.com wrote:
>
> it declares a const member function, which cannot alter ... non-mutable
> data members in the class.

Presumably all member functions, const or otherwise, can't alter non-mutable
data members, to the extent that that non-mutability can be expressed in the
class member definition.

More generally, the caller of a const member function has no guarantee that
the call won't mutate data that can reasonably be thought of as belonging
to the object, in some cases even without the use of const_cast.

There are no circumstances in which const can be equated with pure, so
it provides no help to the compiler and limited help to the programmer
attempting to reason about his code.

Daniel

David Brown

unread,
Apr 13, 2016, 2:43:18 PM4/13/16
to
On 13/04/16 18:13, Daniel wrote:
> On Wednesday, April 13, 2016 at 4:51:21 AM UTC-4, robert...@yahoo.com wrote:
>>
>> it declares a const member function, which cannot alter ... non-mutable
>> data members in the class.
>
> Presumably all member functions, const or otherwise, can't alter non-mutable
> data members, to the extent that that non-mutability can be expressed in the
> class member definition.

"mutable" is a type qualifier that can apply to members of a class. It
means that the member in question /can/ be modified by a "const" member
function. Members that are not declared as mutable cannot be modified
by a const member function (you can cheat, using const_cast or similar
methods, but the results are undefined - and the compiler can optimise
on the assumption that you don't cheat).

>
> More generally, the caller of a const member function has no guarantee that
> the call won't mutate data that can reasonably be thought of as belonging
> to the object, in some cases even without the use of const_cast.

That is correct - as long as you qualify such "private" data as
"mutable". The caller of a const member function does have a guarantee
that data, even if it is private to the object, will not be modified
unless it is mutable.

>
> There are no circumstances in which const can be equated with pure, so
> it provides no help to the compiler and limited help to the programmer
> attempting to reason about his code.
>

const is not the same as "pure", and does not offer quite as many
optimisation opportunities as one might think, but it helps programmers
reason about their code and spot mistakes (by making some kinds of
errors into compile-time errors, and by documenting functionality of the
code), and it provides a number of optimisation chances to the compiler.


Daniel

unread,
Apr 13, 2016, 3:45:13 PM4/13/16
to
On Wednesday, April 13, 2016 at 2:43:18 PM UTC-4, David Brown wrote:
>
> "mutable" is a type qualifier that can apply to members of a class.
> It means that the member in question /can/ be modified by a "const"
> member function.

Missed that, I was interpreting "non-mutable" in it's literal sense.

> Members that are not declared as mutable cannot be modified
> by a const member function [without cheating]

Not entirely, e.g.

class A
{
int* x;

...

void f() const
{
x[0] = 1;
}
};

>
> const is not the same as "pure", and does not offer quite as many
> optimisation opportunities as one might think, but it helps programmers
> reason about their code and spot mistakes (by making some kinds of
> errors into compile-time errors, and by documenting functionality of the
> code), and it provides a number of optimisation chances to the compiler.

const is a hack in a language full of them, I don't think we will see it
copied in more modern languages.

Daniel

Victor Bazarov

unread,
Apr 13, 2016, 3:51:14 PM4/13/16
to
On 4/13/2016 3:44 PM, Daniel wrote:
> On Wednesday, April 13, 2016 at 2:43:18 PM UTC-4, David Brown wrote:
>>
>> "mutable" is a type qualifier that can apply to members of a class.
>> It means that the member in question /can/ be modified by a "const"
>> member function.
>
> Missed that, I was interpreting "non-mutable" in it's literal sense.
>
>> Members that are not declared as mutable cannot be modified
>> by a const member function [without cheating]
>
> Not entirely, e.g.
>
> class A
> {
> int* x;
>
> ...
>
> void f() const
> {
> x[0] = 1;
> }
> };

There is no modification of a *member* here. So, yes, *entirely*.

V
--
I do not respond to top-posted replies, please don't ask

Daniel

unread,
Apr 13, 2016, 4:01:33 PM4/13/16
to
From the user's point of view, the function is mutating data that is owned
by the object.

Daniel

Victor Bazarov

unread,
Apr 13, 2016, 4:38:35 PM4/13/16
to
"Ownership" is not a language feature. The object's data member is 'x'
and *it* is not changed. The same would go if the member were a
reference to it, in which case there is no ownership at all. A 'const'
member function adheres to a contract not to modify the 'this' object
and it doesn't. The compiler ensures it.

Öö Tiib

unread,
Apr 13, 2016, 5:19:16 PM4/13/16
to
C++ has never had transitivity of constness (or volativeness) through
pointers or references (or smart pointers). There is transitivity of
constness to members of containers or arrays.

What is "users point of view" goes from wall to wall. If you need that
transitivity for your "owned objects" (that raw pointer member does no
way insist) then you can write your "owner_ptr" smart pointers that
do have that problem "fixed" and then use only those as members.

Daniel

unread,
Apr 13, 2016, 5:36:32 PM4/13/16
to
On Wednesday, April 13, 2016 at 4:38:35 PM UTC-4, Victor Bazarov wrote:
>
> "Ownership" is not a language feature. The object's data member is 'x'
> and *it* is not changed. The same would go if the member were a
> reference to it, in which case there is no ownership at all. A 'const'
> member function adheres to a contract not to modify the 'this' object

Which is a meaningless contract from the point of view of the user of the
class, the user couldn't care less whether, say, the length and width of
an object are stored as size_t length_, size_t width_ or as size_t*. These
are implementation details. It's just an illustration that the semantics of
const don't correspond to any sensible idea of immutability, and basically
amounts to a language hack.

Daniel

Öö Tiib

unread,
Apr 13, 2016, 5:55:07 PM4/13/16
to
Storing length and width as 'size_t[2]' or as 'std::array<size_t,2>'
or as 'std_pair<size_t,size_t>' may make sense but why to store those
as a raw pointer? If you want to over-engineer so badly then use
'std::vector<size_t>' and you have your transitive constness.

Chris Vine

unread,
Apr 13, 2016, 6:14:55 PM4/13/16
to
Not really "entirely". Static data members can be modified by const
member functions. But perhaps you don't regard them as "members"?

Chris


Robert Wessel

unread,
Apr 13, 2016, 9:47:16 PM4/13/16
to
Brain fart. For some reason I was thinking that was not in C++98...

Victor Bazarov

unread,
Apr 14, 2016, 7:31:51 AM4/14/16
to
Well, they do not *belong* to *objects* which a const function cannot
modify, so... A static member (with proper access) can be modified
without the use of a member function.

Daniel

unread,
Apr 14, 2016, 12:46:50 PM4/14/16
to
On Wednesday, April 13, 2016 at 5:55:07 PM UTC-4, Öö Tiib wrote:
>
> Storing length and width as 'size_t[2]' or as 'std::array<size_t,2>'
> or as 'std_pair<size_t,size_t>' may make sense but why to store those
> as a raw pointer? If you want to over-engineer so badly then use
> 'std::vector<size_t>' and you have your transitive constness.

That's not the point. I think you know what const means, and so so do I. What remains is perspective. My perspective is that const is a poorly
thought out feature, ever by the standards of way back when. What I want to
know when I call a method is whether it has side effects, and const is
silent on that.

Daniel

Alf P. Steinbach

unread,
Apr 14, 2016, 4:26:17 PM4/14/16
to
On 14.04.2016 18:46, Daniel wrote:
>
> <snip> My perspective is that const is a
> poorly thought out feature, ever by the standards of way back when.
> What I want to know when I call a method is whether it has side
> effects, and const is silent on that.

As I recall Andrei was keen on providing a kind of transitive constness
in D. Not sure how that panned out. But it's worth noting that C++ does
not generally provide conceptual level features, but merely the low
level building blocks to create such features. Headers and header
include guard symbols can be used to implement conceptual modules. It
certainly helps to have used a language with direct module support.


Cheers & hth.,

- Alf

Paavo Helde

unread,
Apr 14, 2016, 5:12:17 PM4/14/16
to
On 14.04.2016 23:25, Alf P. Steinbach wrote:
> On 14.04.2016 18:46, Daniel wrote:
>>
>> <snip> My perspective is that const is a
>> poorly thought out feature, ever by the standards of way back when.
>> What I want to know when I call a method is whether it has side
>> effects, and const is silent on that.
>
> As I recall Andrei was keen on providing a kind of transitive constness
> in D. Not sure how that panned out. But it's worth noting that C++ does
> not generally provide conceptual level features, but merely the low
> level building blocks to create such features.

That's right and how it should be. Const propagation is done for example
by higher level classes like std::vector.

Another issue is what exactly are those low level building blocks. Maybe
'const' as defined is not the most useful. It provides some
half-enforced documentation though, so it is not entirely useless either.

Maybe some other aspects like 'pureness' or 'multithread-safeness' would
be more useful or important, but we do not have currently low level
support for them. Especially multithreading seems to be pretty hard to
tackle. An ideal language would detect potential data races and
deadlocks at compile time, but AFAIK we are lightyears away from this.
Please correct me if I am mistaken, it would be a delight!

Cheers
Paavo


Jens Thoms Toerring

unread,
Apr 14, 2016, 5:59:12 PM4/14/16
to
Paavo Helde <myfir...@osa.pri.ee> wrote:
> On 14.04.2016 23:25, Alf P. Steinbach wrote:
> > On 14.04.2016 18:46, Daniel wrote:
> >>
> >> <snip> My perspective is that const is a
> >> poorly thought out feature, ever by the standards of way back when.
> >> What I want to know when I call a method is whether it has side
> >> effects, and const is silent on that.
> >
> > As I recall Andrei was keen on providing a kind of transitive constness
> > in D. Not sure how that panned out. But it's worth noting that C++ does
> > not generally provide conceptual level features, but merely the low
> > level building blocks to create such features.

> That's right and how it should be. Const propagation is done for example
> by higher level classes like std::vector.

> Another issue is what exactly are those low level building blocks. Maybe
> 'const' as defined is not the most useful. It provides some
> half-enforced documentation though, so it is not entirely useless either.

I guess that a lot of this is a question of perception, dependent
on where one's coming from. For me as someone that has taken the
route assembler => C => C++ the way const is used in C++ is rather
easy to grasp and pretty impressive as well when it comes to help
avoiding common mistakes. For someone coming from the other direc-
tion, i.e. from a higher-level language point of view, it might
look much poorer.

On the other hand there's always the question of what one whishes
for. Would it be really always a good thing if one couldn't modify
what a pointer member variable of a const instance of a class points
to? If you e.g. have a pointer to a C-type file pointer in your
class, would it "feel right" to be unable to read from that file
or write to it (since it will, in some way, modify the internal
state of the pointed to FILE object)?

The way of good intentions would be to start distinguishing be-
tween pointers that also should "protect" what's pointed to and
those that don't: we'd need two types of pointers, one for poin-
ting to objects, that can not be changed when the pointer is a
member of a const qualified class instance, and one for pointers
as we have them now. Same, of course, for references. I'll need
some convincing that this would be a desirable feature to have...

Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de

Öö Tiib

unread,
Apr 15, 2016, 12:37:56 PM4/15/16
to
May be you search apples from apricot tree here. Main focus of C++
is on efficiency. Its raw features fit rarely exactly for something and are
even unsafe in clumsy hands. In typical code that we write we however
do not use most of the raw features directly. We do not write 'new' or
'delete' or use raw arrays and naked pointers because there are containers,
iterators and smart pointers.

Making a class with transitive immutability is simple using non-transitive
'const', while other way around it would be tricky. If you need a keyword
that indicates pureness of a function in C++ then quite close to it is
'constexpr'.

Kalle Olavi Niemitalo

unread,
Apr 16, 2016, 10:08:24 AM4/16/16
to
Öö Tiib <oot...@hot.ee> writes:

> What do you mean by "cannot modify the class"?

In C++11, a const member function of a class cannot cause that
class to become derived from additional base classes.

#include <iostream>
#include <type_traits>

class A
{
};

class B
{
public:
template<typename base> void add_base() const {}
};

int main()
{
std::cout.setf(std::ios_base::boolalpha);

// This outputs "false" because B has no base classes.
std::cout << "Is A a base class of B? "
<< std::is_base_of<A, B>::value << std::endl;

// Try to add A as a base class of B.
// However, add_base<A> is a const member function,
// so it cannot actually add base classes to B.
B().add_base<A>();

// This outputs "false" again because the base class was not added.
std::cout << "Is A a base class of B now? "
<< std::is_base_of<A, B>::value << std::endl;
}

// ;)

Alf P. Steinbach

unread,
Apr 16, 2016, 2:04:29 PM4/16/16
to
On 16.04.2016 16:02, Kalle Olavi Niemitalo wrote:
> Öö Tiib <oot...@hot.ee> writes:
>
>> What do you mean by "cannot modify the class"?
>
> In C++11, a const member function of a class cannot cause that
> class to become derived from additional base classes.

↑ nonsense.


Kalle Olavi Niemitalo

unread,
Apr 16, 2016, 3:16:27 PM4/16/16
to
Well spotted! The inability to add a base class to class B at run
time had nothing to do with const vs. non-const member functions.
The real reason for class B not being polymorphic was that
it neither declared nor inherited any virtual functions.

;)

Seriously, I also tried to use SFINAE to select different base
classes for class B depending on whether class B has a member
function with a particular name -- which could then be further
constrained to be a const member function. I believe it is
impossible because class B is incomplete when the compiler is
figuring out its base classes. Besides, it would lead to a
paradox if class B inherits a function with that name from a base
class that was selected because class B had no such function.

Kalle Olavi Niemitalo

unread,
Apr 16, 2016, 5:14:31 PM4/16/16
to
j...@toerring.de (Jens Thoms Toerring) writes:

> The way of good intentions would be to start distinguishing be-
> tween pointers that also should "protect" what's pointed to and
> those that don't: we'd need two types of pointers, one for poin-
> ting to objects, that can not be changed when the pointer is a
> member of a const qualified class instance, and one for pointers
> as we have them now.

That apparently cannot be implemented as a smart pointer template
because the constructors cannot be overloaded according to
whether the object being constructed is const or not.

template<typename T>
class propagating;

template<typename T>
class propagating<T *>
{
T *p;
public:
propagating(T *v): p(v) {}
T &operator *() { return *p; }
const T &operator *() const { return *p; }

// C++ does not support this kind of overloading:
// propagating(propagating &) = default;
// propagating(propagating &) const = default;
// propagating(const propagating &) = delete;
// propagating(const propagating &) const = default;
};

struct X
{
propagating<int *> p;
};

int main()
{
int i1 = 1;
const int i2 = 2;
X x1 { &i1 }; // allowed, as intended
*x1.p = 0; // allowed, as intended
const X x2 { &i2 }; // error, but should be allowed
*x2.p = 0; // error, as intended
X x3 = x2; // allowed, but should be rejected...
*x3.p = -1; // ...because it permits this write to i2
const X x4 = x1; // allowed, as intended
}

If that kind of overloading were allowed, then [dcl.fct] would
have to be modified not to delete top-level cv-qualifiers of
parameters in function declarations like

void f1(X x);
void f2(const X x);

because it should be possible to call f2(x2) but not f1(x2).
0 new messages