Avoiding multiply defined symbols for member functions

D

Dave

Hello all,

Please consider this code:

#ifndef FOO_INCLUDED
#define FOO_INCLUDED
// File: foo.h

class foo
{
public:
// Defined here in the header, implicitly inline
void func_1() {}

void func_2();
};

// Defined here in the header, not implicitly inline
void foo::func_2() {}
#endif

If this file gets included by more than one .cpp file, a link error along
the lines of "multiply defined synbol" will result because of foo::func_2().
Now, let's take foo::func_2() out, leaving only foo::func_1(). There is no
longer an error. This shows that foo::func_1() does not induce this error;
this is due to the fact that it is (implicitly) inline. There is presumably
no foo::func_1() symbol generated since a call to it is never generated. In
lieu of a call, its contents are simply plopped in place.

Now, this raises a question. A compiler is not required to honor an inline
request, even an implicit one. So, it would seem that defining a member
function inside of your class declaration would be very risky. If the
compiler chooses to not make the function inline, your going to get a
"multiply defined symbol" error. Yet, I have never seen this happen, and I
know that it is very common practice to define one or two line member
functions inside of their class' definition. I see this done by experts in
modern C++ literature all the time.

So, what am I missing here? How is it that the way I have declared / defined
foo::func_1() above is not putting me in jeopardy of a "multiply defined
symbol" linker error?

Thanks,
Dave
 
J

John Carson

Dave said:
Hello all,

Please consider this code:

#ifndef FOO_INCLUDED
#define FOO_INCLUDED
// File: foo.h

class foo
{
public:
// Defined here in the header, implicitly inline
void func_1() {}

void func_2();
};

// Defined here in the header, not implicitly inline
void foo::func_2() {}
#endif

If this file gets included by more than one .cpp file, a link error
along the lines of "multiply defined synbol" will result because of
foo::func_2(). Now, let's take foo::func_2() out, leaving only
foo::func_1(). There is no longer an error. This shows that
foo::func_1() does not induce this error; this is due to the fact
that it is (implicitly) inline. There is presumably no foo::func_1()
symbol generated since a call to it is never generated. In lieu of a
call, its contents are simply plopped in place.

Now, this raises a question. A compiler is not required to honor an
inline request, even an implicit one. So, it would seem that defining
a member function inside of your class declaration would be very
risky. If the compiler chooses to not make the function inline, your
going to get a "multiply defined symbol" error. Yet, I have never
seen this happen, and I know that it is very common practice to
define one or two line member functions inside of their class'
definition. I see this done by experts in modern C++ literature all
the time.

So, what am I missing here? How is it that the way I have declared /
defined foo::func_1() above is not putting me in jeopardy of a
"multiply defined symbol" linker error?

Sections 7.1.2/2-4 of the standard read as follows:

"2. A function declaration (8.3.5, 9.3, 11.4) with an inline specifier
declares an inline function. The inline specifier indicates to the
implementation that inline substitution of the function body at the point of
call is to be preferred to the usual function call mechanism. An
implementation is not required to perform this inline substitution at the
point of call; however, even if this inline substitution is omitted, the
other rules for inline functions defined by 7.1.2 shall still be respected.

"3. A function defined within a class definition is an inline function. The
inline specifier shall not appear on a block scope function declaration.

"4. An inline function shall be defined in every translation unit in which
it is used and shall have exactly the same definition in every case (3.2)."

The answer to your puzzle is found in the passage: "even if this inline
substitution is omitted, the other rules for inline functions defined by
7.1.2 shall still be respected."
 
V

Victor Bazarov

Dave said:
Please consider this code:

#ifndef FOO_INCLUDED
#define FOO_INCLUDED
// File: foo.h

class foo
{
public:
// Defined here in the header, implicitly inline
void func_1() {}

void func_2();
};

// Defined here in the header, not implicitly inline
void foo::func_2() {}
#endif

If this file gets included by more than one .cpp file, a link error
along the lines of "multiply defined synbol" will result because of
foo::func_2(). Now, let's take foo::func_2() out, leaving only
foo::func_1(). There is no longer an error. This shows that
foo::func_1() does not induce this error; this is due to the fact
that it is (implicitly) inline. There is presumably no foo::func_1()
symbol generated since a call to it is never generated. In lieu of a
call, its contents are simply plopped in place.

Now, this raises a question. A compiler is not required to honor an
inline request, even an implicit one.

But it has to respect the declaration.
So, it would seem that defining
a member function inside of your class declaration would be very
risky.
Nope.

If the compiler chooses to not make the function inline, your
going to get a "multiply defined symbol" error.
Nope.

Yet, I have never
seen this happen, and I know that it is very common practice to
define one or two line member functions inside of their class'
definition. I see this done by experts in modern C++ literature all
the time.

So, what am I missing here?

You're missing the fact that _declaring_ a function 'inline' changes
things even if in some cases the compiler may choose to create the body
of the function and produce a "real", "out-of-line", call to it.
How is it that the way I have declared /
defined foo::func_1() above is not putting me in jeopardy of a
"multiply defined symbol" linker error?

That's how. "Declared" is the key word here.

V
 
A

Alipha

Dave said:
Hello all,

Please consider this code:

#ifndef FOO_INCLUDED
#define FOO_INCLUDED
// File: foo.h

class foo
{
public:
// Defined here in the header, implicitly inline
void func_1() {}

void func_2();
};

// Defined here in the header, not implicitly inline
void foo::func_2() {}
#endif

If this file gets included by more than one .cpp file, a link error along
the lines of "multiply defined synbol" will result because of foo::func_2().
...

if you wish to inline func_2 but not define it within the class
definition, use the inline keyword:

class foo
{
public:
// Defined here in the header, implicitly inline
void func_1() {}

inline void func_2();
};

void foo::func_2() {}
 

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

No members online now.

Forum statistics

Threads
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top