same name class in different cpps ?

hello, my question is, what will happen if i define the same name class(struct) in different cpp files in one project ?

i.e:
1
2
3
4
5
6
7
8
9
10
11
12
//a.cpp:
struct Handler { something };
void a_func()
{
 use handler defined in this file.   
}
//b.cpp:
struct Handler { something };
void b_func()
{
  use handler defined in this file too
}

I suppose there will not any problems because these same name types are in different compile units. But, actually i really met some problems in my project.
If someone want more detail codes, i will post a simple example later.
Thanks a lot.
I will be curious to take a look at your problem. I have only tested different filename.cpp for same C++ class defined in .h file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//a.h
class A {
  public:
    void hi();
    void lo();
    void med();
}

//a.cpp
#include "a.h"
void A::hi() {
...
}
void A::lo() {
...
}

//b.cpp
#include "a.h"
void A::med() {
...
}
@sohguanh
Thanks for your reply.
Here is an example which cause my debugger(vs2005) report an error:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//test.cpp
#include <stdio.h>
#include <string.h>

struct Handler
{
    Handler() { strcpy( d, "test Handler" ); }
    char d[32];
};

extern void cpp_func();

int main(void)
{
    Handler h;
    printf( "test, %s.\n", h.d );
    cpp_func();
    return 0;
}
//cpp.cpp
#include <stdio.h>

struct Handler
{
    Handler() : d( 0 ) { }
    int d;
};

void cpp_func()
{
    Handler h;
    printf( "cpp_func: %d.\n", h.d );
}

The error is 'h' in 'cpp_func' has destroyed the stack in cpp_func. I debug this program in asm mode and found that in 'cpp_func' it called the wrong Handler constructor. It didnot call the constructor in cpp.cpp file, instead the constructor in test.cpp.

But the size of variable 'h' is still 4, so 'strcpy' in test.cpp:Handler cause the problem.

Actually in my real project the problem is fifferent, but i think the 2 problems are some like.
I think you are depending on the compiler to parse struct Handler in test.cpp FIRST and then parse struct Handler in cpp.cpp or vice versa ?

I think it is very dangerous for us to assume how the C++ compiler/linker parse the struct Handler. I believe if you change the cpp.cpp or test.cpp struct Handler to something else the problem should go away ?

To me I feel you are trying to define TWO different struct but they share the SAME name ? I think this may confuse the compiler/linker. We should signal our intention clear to the compiler/linker instead.

My try-out code intention is clear. ONE C++ class but implementation spread to multiple files all "supporting" that ONE class in the .h This is clear and it works.
Change the Handler name can solve this problem. But i still want to know how the compiler/linker handle this stuff. Anyway, thanks you a lot.
I believe that the linker doesn't care too much what the actual definition of a class/struct is.

.o files are concerned with functions, and raw data, not any class information. For C++ this means that the name of a member function must include some metadata about the class that it's a member of, for disambiguation with global functions, but that metadata is concerned with name only, not the actual structure behind the name.

Basically, it seems to me like the behavior is that the linker would happily interchange functions acting on same-named classes, as it assumes they're for the same class. Bad things ensue after that.

What confuses me is that there wouldn't be a linking collision between the constructors in the two structs. They should have the same prototypes and class names, so shouldn't they produce same named symbols in the output?

I'm confused about that too. I suppose the linker or the compiler should divide my 2 same name classes. Like overload functions, they maybe append some more information like:
1
2
3
4
5
struct Handler_cpp;
struct Handler_test;
//and in my 2 cpp files, these 'h' variables should be take care also:
Handler_cpp h;
Handler_test h;

But the linke does not do this for me. There isnot even any warning about the name collision. As you said, if the struct name is still 'Handler', the constructor name will be the same too, if so there must be a linker error.

Hi stravant, kevinlynx both of you raise very valid questions but a developer who develop compiler/linker would be in a better position to answer our queries. Let's wait for a compiler/linker developer to reply in this forum.

PS Let's hope this forum attract a compiler/linker developer
the linker would start reading from left to right, the object files included at the link time.
this way it would resolve all the missing symbols for the final binary to be generated.

As your test.cpp has the handler already, it is resolved. Now, your cpp_func() in cpp.cpp prints "%d" from the string in Handler.d

This is the problem.

The below program shows what would be called in main() and cpp_func() clearly. It would be a single Handler first found in test.cpp.

===
testBox # cat test.cpp
#include <iostream>
using namespace std;
struct Handler
{
Handler()
{
cout << "Handler constructor from test.cpp" << endl;
}
};

extern void cpp_func();

int main(void)
{
Handler h;
cpp_func();
return 0;
}

testBox # cat cpp.cpp
//cpp.cpp
#include <iostream>
using namespace std;
struct Handler
{
Handler()
{
cout << "Handler constructor from: cpp.cpp" << endl;
}
};

void cpp_func()
{
Handler h;
}

testBox #
testBox # g++ -c cpp.cpp
testBox # ls -l cpp*
-rw-r--r-- 1 root root 187 Oct 5 14:10 cpp.cpp
-rw-r--r-- 1 root root 2320 Oct 5 14:11 cpp.o
testBox # g++ -o test1 test.cpp cpp.o
testBox # ls -lrt test*
-rw-r--r-- 1 root root 229 Oct 5 14:10 test.cpp
-rwxr-xr-x 1 root root 7104 Oct 5 14:12 test1
testBox # ./test1
Handler constructor from test.cpp
Handler constructor from test.cpp
testBox #

===
Topic archived. No new replies allowed.