gpt4 book ai didi

c++ - 退出时覆盖不明确的函数时代码如何运行?

转载 作者:行者123 更新时间:2023-12-02 10:39:40 25 4
gpt4 key购买 nike

当存在覆盖模糊函数时,我无法完全理解代码结果。

我有一个库libMy ,其中包含两个类 AB .

代码如下

// A.h
#ifndef included_A_h
#define included_A_h

class A
{
public:
void print();
};

#endif
// A.cpp
#include "A.h"
#include <iostream>
void A::print()
{
std::cout << "A from library" << std::endl;
}
// B.h
#ifndef included_B_h
#define included_B_h
class A;
class B
{
public:
void printA(A &a);
};

#endif
// B.cpp
#include "B.h"
#include "A.h"
void B::printA(A &a)
{
a.print();
}

我有两个主要函数,它们可以用库生成两个可执行文件。

可以发现Main*.cpp看起来很奇怪。为什么需要看起来像这样在底部解释。

// MainUsingCPP.cpp
#include <iostream>
#define included_A_h
class A
{
public:
void print()
{
std::cout << "A from Main" << std::endl;
}
};

#include "B.cpp" // note: using B.cpp here

int main()
{
A obj_a;
B obj_b;
obj_b.printA(obj_a);
return 0;
}
// MainUsingH.cpp
#include <iostream>
#define included_A_h
class A
{
public:
void print()
{
std::cout << "A from Main" << std::endl;
}
};

#include "B.h" // note: using B.h here

int main()
{
A obj_a;
B obj_b;
obj_b.printA(obj_a);
return 0;
}

通过下面的代码,我们可以编译库,并生成可执行文件。

# generate library
g++ -c A.cpp
g++ -c B.cpp
ar -crv libMy.a A.o B.o

# compile case CPP
g++ MainUsingCPP.cpp -L . -lMy -o MainUsingCPP

# compile case H
g++ MainUsingH.cpp -L . -lMy -o MainUsingH

并运行可执行文件,结果如下

./MainUsingH
A from library
./MainUsingCPP
A from Main

我的问题是:

(1)为什么代码可以编译通过?

拍摄MainUsingCPP.cpp考虑到库,A类被重新定义。所以我们有两个A::print()版本。来自 MainUsingCPP.cpp 的一个另一个来自图书馆。在这个阶段,A::print()是暧昧的。为什么代码可以编译?链接器如何区分它们?链接器如何决定需要使用哪个版本的函数?

(2)如何理解结果?

为什么两个可执行文件的结果不同?为什么链接器选择A::print()来自 MainUsingH.cpp 的图书馆并选择A::print()来自主干 MainUsingCPP.cpp

为什么 Main.cpp 看起来很奇怪

A是一个类并且 BA的用户。在 MainUsingCPP.cppA的功能似乎可以重新定义。即A即使 A 没有虚函数,也可以模拟单元测试!

更多可以参见Peter Dotchev在fake/mock nonvirtual C++ methods中的回答

感谢您的宝贵时间!

最佳答案

(1)Why the code can compile?

One Definition Rule说的是

Only one definition of any variable, function, class type, enumeration type, ... or template is allowed in any one translation unit

这就满足了,因为每个目标文件对应一个不同的翻译单元。

编译(翻译单元到目标文件)就这么多 - 现在是链接:

One and only one definition of every non-inline function or variable ... is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined.

所以你的程序行为是未定义的,但是编译器不需要告诉你,甚至不需要自己确定这一点。

<小时/>

(2)How to understand the result?

不要试图理解未定义的行为,它的定义是未定义的。

如果您想了解特定编译器如何处理损坏的代码,请让它为您扩展两个主要翻译单元(对于 GCC 使用 -E)。但是,这实际上是关于编译器而不是语言的问题,因为语言明确没有定义这种情况。

关于c++ - 退出时覆盖不明确的函数时代码如何运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59191738/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com