存在时的代码如何运行覆盖不明确的功能? [英] How the code run when exist override ambigous function?

查看:71
本文介绍了存在时的代码如何运行覆盖不明确的功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当存在重写模糊函数时,我无法完全理解代码结果.

I can not fully understand the code result when exist override ambigous function.

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

I have a libray libMy, which contains two class A and B.

代码如下所示

// 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();
}

我有两个主要功能,它们可以使用该库生成两个可执行文件.

I have two main function, they can generate two executable file with the library.

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

It can be found that Main*.cpp looks strange. Why need look like so is explained at the bottom.

// 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;
}

使用以下代码行,我们可以编译库并生成可执行文件.

With follow line, we can compile the library, and generate executable file.

# 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

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

And run the executable file, result shown as follow

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

我的问题是:

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

考虑到MainUsingCPP.cpp和库,重新定义了类A.因此,我们有两个A::print()版本.一个来自MainUsingCPP.cpp,另一个来自库.在这些阶段,A::print()尚不明确.为什么代码可以编译?链接器如何区分它们?链接器如何确定它需要使用哪个功能的版本?

Taken MainUsingCPP.cpp and library into consideration, the class A is redefined. So we have two A::print() version. The one from MainUsingCPP.cpp and another from library. At these stage, the A::print() is ambigous. Why the code can compile? How the linker distinguish them? How the linker decide which version of function it needs to use?

(2)如何理解结果?

为什么两个可执行文件中的结果不同? 为什么链接器从MainUsingH.cpp的库中选择A::print()并从MainUsingCPP.cpp

Why the result in two executable file different? Why the linker choose A::print() from library in MainUsingH.cpp and choose A::print() from Main in MainUsingCPP.cpp

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

A是类,BA的用户.在MainUsingCPP.cpp中,A的功能似乎可以重新定义.也就是说,即使A没有虚拟功能,也可以模拟A进行单元测试!

A is a class and B is A's user. In MainUsingCPP.cpp, the A's funtion seems can be redefined. That is, A is can be mocked for unit test even if A do not have virtual function!

更多信息可以在伪造/模拟非虚拟C ++方法中看到Peter Dotchev的答案

More can see Peter Dotchev's answer in the fake/mock nonvirtual C++ methods

感谢您的时间!

推荐答案

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

(1)Why the code can compile?

一个定义规则表示

在任何一个翻译单元中,只允许对变量,函数,类类型,枚举类型,...或模板进行任何定义

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

这是可以满足的,因为每个目标文件都对应一个不同的翻译单元.

and this is satisfied, because each object file corresponds to a different translation unit.

用于编译的工作量很大(从翻译单元到目标文件)-现在可以进行链接:

So much for compilation (of translation units to object files) - now for linking:

在整个程序(包括任何标准库和用户定义库)中,都需要每个非内联函数或变量的一个且仅一个定义. 不需要编译器来诊断此违规行为,但未定义违反该行为的程序的行为.

所以您的程序行为是不确定的,但是编译器不需要告诉您,甚至无需自行决定.

So your program behaviour is undefined, but the compiler is not required to tell you, or even to determine this itself.

(2)如何理解结果?

(2)How to understand the result?

停止尝试理解未定义的行为,这是未定义的.

Stop trying to understand Undefined Behaviour, it's undefined by definition.

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

If you want to understand what your specific compiler did with your broken code, then get it to expand the two main translation units for you (using -E for GCC). But, it's really a question about your compiler rather than the language, since the language explicitly didn't define this situation.

这篇关于存在时的代码如何运行覆盖不明确的功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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