C++ 中如何解决这些名称冲突?

发布于 2024-11-15 04:24:49 字数 2011 浏览 2 评论 0原文

假设我有这样的物理结构:

/
  +-- conflicttest
  |     +-- A.cpp
  |     +-- A.h
  |     +-- main.cpp
  +-- libconflict
  |     +-- conflict
  |     |     +-- A.h
  |     |     +-- B.h
  |     +-- A.cpp
  |     +-- B.cpp

这些是 libconflict 的来源,深吸一口气:

libconflict 中的 class B header:

// libconflict B.h
class B
{
public:
    void bar();
protected:
    int j_;
};

class B libconflict 中的实现:

// libconflict B.cpp
#include "conflict/B.h"

void B::bar()
{
    std::cout << "B::bar" << std::endl;
}

class A libconflict 中的 标头:

// libconflict A.h
# include "conflict/B.h"

class A : public B
{
public:
    A();
private:
    int i_;
};

libconflict 中的 class A 实现:

#include "conflict/A.h"

A::A()
{
    std::cout << "libconflict A is alive" << std::endl;
    i_ = 51; // some random fields and values... I should admit I am lost
    j_ = 47;
}

现在是冲突测试的来源,几乎结束了:

conflicttest 中的 class A 标头:

// conflicttest A.h
class A
{
public:
    A();
    void foo();
};

class A< /代码>实施在冲突测试中:

// conflicttest A.cpp
#include "A.h"

A::A()
{
    std::cout << "A is alive" << std::endl;
}

void A::foo()
{
    std::cout << "A::foo" << std::endl;
}

最后,main.cpp

// main.cpp in conflicttest
#include "conflict/A.h"

int main()
{
    B* b = new A;
    b->bar();
return 0;
}

唷...我正在使用 Visual Studio 2010 来构建此解决方案。 conflicttest 是一个链接到静态库libconflict 的可执行文件。 这编译起来就像一个魅力,但是,不管你信不信,输出是:

A is alive
B::bar

链接器实际上使用来自 conflicttest 的符号 A ,它绝对不是 B< /code> 更糟糕的是,它可以调用 B::bar()

我迷路了,为什么编译器不抱怨?

Say I have this physical structure:

/
  +-- conflicttest
  |     +-- A.cpp
  |     +-- A.h
  |     +-- main.cpp
  +-- libconflict
  |     +-- conflict
  |     |     +-- A.h
  |     |     +-- B.h
  |     +-- A.cpp
  |     +-- B.cpp

These are the sources of libconflict, take a deep breath:

class B header in libconflict:

// libconflict B.h
class B
{
public:
    void bar();
protected:
    int j_;
};

class B implementation in libconflict:

// libconflict B.cpp
#include "conflict/B.h"

void B::bar()
{
    std::cout << "B::bar" << std::endl;
}

class A header in libconflict:

// libconflict A.h
# include "conflict/B.h"

class A : public B
{
public:
    A();
private:
    int i_;
};

class A implementation in libconflict:

#include "conflict/A.h"

A::A()
{
    std::cout << "libconflict A is alive" << std::endl;
    i_ = 51; // some random fields and values... I should admit I am lost
    j_ = 47;
}

Now the sources of conflicttest, it's almost over:

class A header in conflicttest:

// conflicttest A.h
class A
{
public:
    A();
    void foo();
};

class A implementation in conflicttest:

// conflicttest A.cpp
#include "A.h"

A::A()
{
    std::cout << "A is alive" << std::endl;
}

void A::foo()
{
    std::cout << "A::foo" << std::endl;
}

and finally, main.cpp:

// main.cpp in conflicttest
#include "conflict/A.h"

int main()
{
    B* b = new A;
    b->bar();
return 0;
}

Phew... I am using Visual Studio 2010 to build this solution. conflicttest is an executable which is linked against the static library libconflict.
This compiles like a charm, but, believe it or not, the output is :

A is alive
B::bar

The linker actually uses the symbol A from conflicttest which is absolutely not a B and worse, it can invoke B::bar().

I am lost, how come the compiler doesn't complain?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

债姬 2024-11-22 04:24:50

您违反了单一定义规则

编译器没有抱怨,因为它在跨越翻译单元边界时可以检测到的东西是有限的。

You have violated the One Definition Rule.

The compiler didn't complain because it is limited in the things it can detect when crossing translation unit boundaries.

绝不放开 2024-11-22 04:24:50

我猜你实际上并没有链接你的conflictlib。但实际上,不要这样做。如果您绝对必须,请使用名称空间。

I'm guessing you aren't actually linking your conflictlib. But really, just don't do that. If you absolutely MUST, use namespaces.

平安喜乐 2024-11-22 04:24:50

答案很简单。你对编译器撒了谎,作为回报,编译器也将你的谎言回馈给你。函数的内部实现是这样的,它们只是排列在每个类的某个函数表中。当您有不同的类声明时,编译器会根据它推导函数表,但推导是错误的。该表中没有函数名称,因此编译器无法检测到错误情况。

The answer is very simple. You have lied to compiler, and in return the compiler is serving your lie back to you. Internal implementation of functions is such that they are just lined up in some function table for each class. When you have different class declaration the compiler deduces the function table according to it, but the deduction is wrong. In this table there are no function names, so compiler can't detect the fault condition.

九歌凝 2024-11-22 04:24:50

您对 A 类有两个不同的定义。这违反了 ODR。因此该程序不是有效的 C++ 程序。编译器不需要诊断此错误。

You have two different definitions of class A. This is a violation of ODR. The program therefore is not a valid C++ program. Compilers are not required to diagnose this error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文