在不同的C ++文件中有相同的类名 [英] Same class name in different C++ files

查看:203
本文介绍了在不同的C ++文件中有相同的类名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果两个C ++文件具有相同名称的类的不同定义,那么当它们被编译和链接时,即使没有警告也会抛出异常。例如,

If two C++ files have different definitions of classes with the same name, then when they are compiled and linked, something is thrown out even without a warning. For example,

// a.cc
class Student {
public:
    std::string foo() { return "A"; }
};
void foo_a()
{
    Student stu;
    std::cout << stu.foo() << std::endl;
}

// b.cc
class Student {
public:
    std::string foo() { return "B"; }
};
void foo_b()
{
    Student stu;
    std::cout << stu.foo() << std::endl;
}



当使用g ++编译和链接在一起时,两个都将输出A a.cc在命令行顺序中位于b.cc之前)。

When compiled and linked together using g++, both will output "A" (if a.cc precedes b.cc in the command line order).

类似的主题是这里。我看到命名空间会解决这个问题,但我不知道为什么链接器甚至不发出警告。如果类的一个定义有额外的函数没有定义在另一个,说如果b.cc更新为:

A similar topic is here. I see namespace will solve this problem but I don't know why the linker doesn't even shoot a warning. And if one definition of the class has extra function that isn't defined in another, say if b.cc is updated as:

// b.cc
class Student {
public:
    std::string foo() { return "B"; }
    std::string bar() { return "K"; }
};
void foo_b()
{
    Student stu;
    std::cout << stu.foo() << stu.bar() << std::endl;
}

然后stu.bar感谢任何人可以告诉我编译器和链接器在这种情况下如何工作。

Then stu.bar() works well. Thanks to anyone who can tell me how the compiler and linker work in such situation.

另外一个问题是,如果类在头文件中定义,用未命名的命名空间避免这种情况?是否有任何副作用?

As an extra question, if classes are defined in header files, should they always be wrapped with unnamed namespace to avoid such situation? Is there any side effects?

推荐答案

这违反了一个定义规则(C ++ 03,3.2 / 5一个定义规则),其中(除了别的之外):

This is a violation of the one definition rule (C++03, 3.2/5 "One definition rule"), which says (among other things):


可以有一个类类型的多个定义),...
,只要每个定义出现在不同的
翻译单元中,并且提供的定义满足以下
要求。假设这样的实体在多于一个
翻译单元中被定义为D,则

There can be more than one definition of a class type (clause 9), ... in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit, then


  • D的每个定义将由相同

如果违反一个定义规则,行为是未定义的

If you violate the one definition rule, the behavior is undefined (which means that strange things can happen).

链接器会看到 Student :: foo()的多个定义: a的对象文件和b中的一个。但是它不抱怨这个;它只是选择两个中的一个(当它发生,它遇到的第一个)。这种软处理重复的函数显然只发生在内联函数。对于非内联函数,链接器抱怨多个定义,并拒绝生成可执行文件(可能有一些选项可以放宽此限制)。 GNU ld 和MSVC的链接器以这种方式工作。

The linker sees multiple definitions of Student::foo() - one in a's object file and one in b's. However it doesn't complain about this; it just selects one of the two (as it happens, the first one it comes across). This 'soft' handling of duplicate functions apparently happens only for inline functions. For non-inline functions, the linker will complain about multiple definitions and will refuse to produce an executable (there may be options that relax this restriction). Both GNU ld and MSVC's linker behave this way.

这种行为有些意义;内联函数需要在它们使用的每个转换单元中可用。在通常情况下,它们需要具有非内联版本(以防调用未内联或者函数的地址被占用)。 inline 实际上只是一个关于单一定义规则的自由传递 - 但是为了工作,所有的内联定义需要是一样的。

The behavior makes some sense; inline functions need to be available in every translation unit they're used in. And in the general case they need to have non-inline versions available (in case the call isn't inlined or if the function's address is taken). inline is really just a free pass around the one-definition rule - but for it to work, all the inline definitions need to be the same.

当我看到目标文件的转储,我没有看到任何明显的解释我如何链接器知道一个函数是允许有多个定义,而其他的不是,但我确定有一些标志或记录,只是这样。不幸的是,我发现链接器和目标文件的细节的工作没有特别详细的记录,所以精确的机制可能会对我是一个谜。

When I look at dumps of the object files, I don't see anything obvious that explains to me how the linker knows that one function is permitted to have multiple definitions and others aren't, but I'm sure there's some flag or record which does just that. Unfortunately, I find that the workings of the linker and object file details aren't particularly well documented, so the precise mechanism will probably remain a mystery to me.

至于您的第二个问题:


另外一个问题是,如果类在头文件中定义,应该是
,命名空间避免这种情况?
是否有副作用?

As an extra question, if classes are defined in header files, should they always be wrapped with unnamed namespace to avoid such situation? Is there any side effects?

你几乎肯定不想这样做每个类都是一个不同类型在每个翻译单元中,因此技术上类的实例不能从一个翻译单元传递到另一个翻译单元(通过指针,引用或复制)。此外,你最终会有多个静态成员的实例。

You almost certainly don't want to do this each class would be a distinct type in each translation unit, so technically instances of the class they couldn't be passed from one translation unit to another (by pointer, reference or copying). Also, you'd end up with multiple instances of any static members. That probably wouldn't work well.

将它们放在不同的命名命名空间中。

Put them in different, named namespaces.

这篇关于在不同的C ++文件中有相同的类名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆