overloading based on function being const

S

subramanian100in

The following is a beginner's question.

Suppose TYPE1 and TYPE2 are two types for which suitable ctors and
operator= are defined.

Suppose I have

class Test
{
TYPE1 mem1;
TYPE2 mem2;

public:
Test & member1(const TYPE1 & val1);
Test & member2(const TYPE2 & val2);

Test & display( ) { /* display mem values */ return *this; }

const Test & display( ) const { /* display mem values */ return
*this; }
};

Test & Test::member1(const TYPE1 & val1)
{
mem1 = val1;
return *this;
}

Test & Test::member2(const TYPE2 & val2)
{
mem2 = val2;
return *this;
}

Suppose I define,
TYPE1 val1;
TYPE2 val2;

Test obj;
obj.display( ).member1(val1).member2(val2).display( );

const Test const_obj;
const_obj.display( );

Suppose the body of both the display( ) functions are the same. That
is, display( ) does not modify the data members of the object. The non-
const version of display( ) function is provided only for chaining.
The const version of display( ) function is provided to be called on
const Test objects. Given this, I have the following questions:

1)Is it advisable to overload a function like display( ) only on const
(everything else being the same for this function) for chaining
purpose when it does not modify the data members of the object

2) When is overloading a function, only on const inevitable ?

Kindly explain

Thanks
V.Subramanian
 
V

Victor Bazarov

The following is a beginner's question.

Suppose TYPE1 and TYPE2 are two types for which suitable ctors and
operator= are defined.

Suppose I have

class Test
{
TYPE1 mem1;
TYPE2 mem2;

public:
Test & member1(const TYPE1 & val1);
Test & member2(const TYPE2 & val2);

Test & display( ) { /* display mem values */ return *this; }

const Test & display( ) const { /* display mem values */ return
*this; }
};

Test & Test::member1(const TYPE1 & val1)
{
mem1 = val1;
return *this;
}

Test & Test::member2(const TYPE2 & val2)
{
mem2 = val2;
return *this;
}

Suppose I define,
TYPE1 val1;
TYPE2 val2;

Test obj;
obj.display( ).member1(val1).member2(val2).display( );

const Test const_obj;
const_obj.display( );

Suppose the body of both the display( ) functions are the same. That
is, display( ) does not modify the data members of the object. The
non- const version of display( ) function is provided only for
chaining. The const version of display( ) function is provided to be
called on const Test objects. Given this, I have the following
questions:

1)Is it advisable to overload a function like display( ) only on const
(everything else being the same for this function) for chaining
purpose when it does not modify the data members of the object

If they would do exactly the same, and both would not attempt to
modify the object, why have the non-const version AT ALL?
2) When is overloading a function, only on const inevitable ?

When you need different behaviour.

V
 
B

Barry

The following is a beginner's question.

Suppose TYPE1 and TYPE2 are two types for which suitable ctors and
operator= are defined.

Suppose I have

class Test
{
TYPE1 mem1;
TYPE2 mem2;

public:
Test & member1(const TYPE1 & val1);
Test & member2(const TYPE2 & val2);

Test & display( ) { /* display mem values */ return *this; }

const Test & display( ) const { /* display mem values */ return
*this; }
};

Test & Test::member1(const TYPE1 & val1)
{
mem1 = val1;
return *this;
}

Test & Test::member2(const TYPE2 & val2)
{
mem2 = val2;
return *this;
}

Suppose I define,
TYPE1 val1;
TYPE2 val2;

Test obj;
obj.display( ).member1(val1).member2(val2).display( );

const Test const_obj;
const_obj.display( );

Suppose the body of both the display( ) functions are the same. That
is, display( ) does not modify the data members of the object. The non-
const version of display( ) function is provided only for chaining.
The const version of display( ) function is provided to be called on
const Test objects. Given this, I have the following questions:

1)Is it advisable to overload a function like display( ) only on const
(everything else being the same for this function) for chaining
purpose when it does not modify the data members of the object

No need to define a non-const member function if their body are indentical;

It has one case that I can recall, when both member functions are needed

Type const& func() const;
Type & func();

For code reuse, you can write this way:

Type& func()
{
const_cast<Klass*>func(this)->func();
// func() const must return non-const Type object
}


I recalled that this NG or c.l.c++.m has some discussion on this, some
folk even invent some macro to ease this Paired-Member-Function(TM) work.

2) When is overloading a function, only on const inevitable ?

I'm not sure what you mean.

But if I don't get you wrong,
(1) already has your answer.
prefer const member function to non-const one
 
V

Victor Bazarov

Barry said:
[..]
It has one case that I can recall, when both member functions are
needed
Type const& func() const;
Type & func();

For code reuse, you can write this way:

Type& func()
{
const_cast<Klass*>func(this)->func();
// func() const must return non-const Type object

First of all, there has to be a return value. So, following your
pattern it would be

return const_cast<Type&>(const_cast<const Klass*>(this)->func());
// I think you missed the qualifier ^^^^^ here

which is a BAD IDEA(tm) because it promotes undefined behaviour. The
const version of 'func' may return a reference to some truly constant
memory, and the caller may end up wanting to change the return value
somehow: KABOOM!

It would be better to duplicate the code to avoid having to deal with
const casts.
I recalled that this NG or c.l.c++.m has some discussion on this, some
folk even invent some macro to ease this Paired-Member-Function(TM)
work. [..]

V
 
B

Barry

The following is a beginner's question.

Suppose TYPE1 and TYPE2 are two types for which suitable ctors and
operator= are defined.

Suppose I have

class Test
{
TYPE1 mem1;
TYPE2 mem2;

public:
Test & member1(const TYPE1 & val1);
Test & member2(const TYPE2 & val2);

Test & display( ) { /* display mem values */ return *this; }

const Test & display( ) const { /* display mem values */ return
*this; }
};

Test & Test::member1(const TYPE1 & val1)
{
mem1 = val1;
return *this;
}

Test & Test::member2(const TYPE2 & val2)
{
mem2 = val2;
return *this;
}

Suppose I define,
TYPE1 val1;
TYPE2 val2;

Test obj;
obj.display( ).member1(val1).member2(val2).display( );

const Test const_obj;
const_obj.display( );

Suppose the body of both the display( ) functions are the same. That
is, display( ) does not modify the data members of the object. The non-
const version of display( ) function is provided only for chaining.
The const version of display( ) function is provided to be called on
const Test objects. Given this, I have the following questions:

1)Is it advisable to overload a function like display( ) only on const
(everything else being the same for this function) for chaining
purpose when it does not modify the data members of the object

2) When is overloading a function, only on const inevitable ?

seeing your subject,
it's not overloading, const/non-const members are totally functions
(different signature).
 
V

Victor Bazarov

Barry said:
seeing your subject,
it's not overloading, const/non-const members are totally functions
(different signature).

It's overloading as long as the *name* of the function is the same
and they are both declared in the same *scope*.

V
 
B

Barry

Victor said:
Barry said:
[..]
It has one case that I can recall, when both member functions are
needed
Type const& func() const;
Type & func();

For code reuse, you can write this way:

Type& func()
{
const_cast<Klass*>func(this)->func();
// func() const must return non-const Type object

First of all, there has to be a return value. So, following your
pattern it would be

return const_cast<Type&>(const_cast<const Klass*>(this)->func());
// I think you missed the qualifier ^^^^^ here

Yeh, you are right.
which is a BAD IDEA(tm) because it promotes undefined behaviour. The
const version of 'func' may return a reference to some truly constant
memory, and the caller may end up wanting to change the return value
somehow: KABOOM!

I presumed that the returned object is modifiable. when returned by
const member function, it adds constness.

But my intent is actually to show that, we can have different return
type on the Pair-Member-Function.
 
B

Barry

Victor said:
It's overloading as long as the *name* of the function is the same
and they are both declared in the same *scope*.

Yeh, you are right.

I has one rule in mind : we can't overloaded a function only by return type.

But the compiler treats const/non-const member functions specially

Type1 A::func(A * this, ...);
Type2 A::func(A const* this, ...);

I did check /overload/'s definition.
When two or more different declarations are specified for a single name
in the same scope, that name is said to be overloaded.

struct A
{
int i;
};

struct B : A
{
int i; // overload if I get the standard right
}

Thanks
 
B

Barry

Barry said:
Yeh, you are right.

I has one rule in mind : we can't overloaded a function only by return
type.

But the compiler treats const/non-const member functions specially

Type1 A::func(A * this, ...);
Type2 A::func(A const* this, ...);

I did check /overload/'s definition.
When two or more different declarations are specified for a single name
in the same scope, that name is said to be overloaded.

struct A
{
int i;
};

struct B : A
{
int i; // overload if I get the standard right

Sorry, again, not the same *scope*
 
S

subramanian100in

When you need different behaviour.

V

Kindly explain what is meant by behaviour of a function ? Does it mean
the task performed by a function - say for example finding the square
root of a function ?

Kindly give the body of a function explaining what is meant by
behaviour of a function.

Thanks
V.Subramanian
 
J

Juha Nieminen

Kindly explain what is meant by behaviour of a function ? Does it mean
the task performed by a function - say for example finding the square
root of a function ?

One typical example of a non-const and a const member function doing a
"different" thing is the begin() member function of STL containers: If
you call the non-const version it will return an 'iterator' (which
allows you modifying the element pointed by the iterator) but if you
call the const version it will return a 'const_iterator' (which will not
allow modification).

The implementations of these two functions are basically different:
They instantiate and return completely different classes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,076
Latest member
OrderKetoBeez

Latest Threads

Top