C++ C++;共享库:纯虚拟函数不会导致链接错误

C++ C++;共享库:纯虚拟函数不会导致链接错误,c++,linker,shared-libraries,pure-virtual,C++,Linker,Shared Libraries,Pure Virtual,我一直在努力理解为什么我可以在我使用的库中没有实现的头文件中创建纯虚拟函数,并且这不会导致链接甚至运行时失败。。 上面的内容可能有点不精确,但这里有一些代码来支持它 以下是接口定义: class A { public: static A* Create(); virtual ~A() {} virtual status_t start() = 0; virtual status_t stop() = 0; }; 我有一个C++共享库,包含一个实现“AIMIL

我一直在努力理解为什么我可以在我使用的库中没有实现的头文件中创建纯虚拟函数,并且这不会导致链接甚至运行时失败。。 上面的内容可能有点不精确,但这里有一些代码来支持它

以下是接口定义:

class A
{
public:
    static A* Create();

    virtual ~A() {}

    virtual status_t start() = 0;
    virtual status_t stop() = 0;
};

我有一个C++共享库,包含一个实现“AIMIL”+ A::CREATE()函数(见下文):

我构建了共享库-没问题。 现在,我在类A的头文件中添加了另一个纯虚拟函数:

class A
    {
    public:
        static A* Create();

        virtual ~A() {}

        virtual status_t start() = 0;
        virtual status_t stop() = 0;
        virtual status_t write() = 0;
    };
我创建了一个使用它的测试应用程序:

void main()
{
    A* a = A::Create();
    a->start();
    a->stop();
    a->write();
}
现在我理解了上面的编译,但我认为它会链接失败,因为在共享库中没有write()调用的实现。 即使在运行时,也不会发生崩溃或任何事情。似乎写入调用被跳过了。有人能帮我解释一下吗?非常感谢:-)


谢谢-很抱歉问了这么长的问题,我很难用“一行”来解释确切的问题。

纯虚拟函数在链接过程中不会导致任何故障。相反,如果试图实例化抽象类型的对象,纯虚拟函数将导致编译错误


提醒-抽象类型是指(通过继承直接或间接地)至少有一个未被重写的纯虚拟函数的类型。

如果以前构建过解决方案,则可能会编译或生成该函数。这意味着它正在使用旧的目标代码。尝试对解决方案进行干净的构建,然后重新构建它。清洗完溶液后。然后尝试编译继承的类。另一件可能值得关注的事情是,您已将继承的类声明为:

类AImpl:A{…}

我的问题是,
AImpl
是如何从
A
继承的?您打算继承
公共
受保护
还是
私有
继承

编辑


如果您将此作为库链接,并且当前解决方案未显示任何编译、生成、链接错误;这是因为您当前的解决方案使用的是已构建的旧
lib
dll
。如果你回到你的库解决方案中,进行一个干净的构建,它不应该被编译,因此你不会有一个更新版本的库来链接。

发生的事情是共享库是用一个版本的
a
类构建的,而可执行二进制文件是用不同的版本构建的。此时,您已经违反了一个定义规则,编译器可以自由地执行任何操作,包括成功地编译和链接代码。在这种情况下不需要编译器诊断。

您真的确定在更改代码后它会重新编译吗?你能强制重建吗?是的,我确信它被重新编译了。但在我看来,编译器不应该抱怨。代码没问题。但是库中缺少实现,所以我会猜到一个链接错误。您是否也重新编译了库?我猜编译应该在
A::create
中失败,因为
AImpl
是抽象的。不,我没有编译库-但问题是-我很惊讶我可以编译/链接一个旧库,而没有得到任何警告。从一般评论看来,这确实是意料之中的!!感谢您的快速回答-您的意思是说,当我链接使用旧版本a的库时,上述内容不会导致任何错误吗?谢谢。你是对的,真正的代码具有公共继承性。我会更新帖子来说明这一点。我知道重新编译共享库(具有实现)将导致编译错误。但令我惊讶的是,我可以向头文件添加新的纯虚拟方法,而不会在使用共享库的应用程序中出现任何编译/链接错误。即使在运行时,我也没有收到错误-只是跳过调用似乎是什么?@user6014883我编辑了我的答案,添加了一个新的部分,解释了链接库会发生什么。是的,谢谢你的评论。我从评论中了解到,我确实不应该期望旧库出现任何编译/链接错误。这对我来说有点令人惊讶,但我将不得不处理这一点:-)谢谢-是的,这似乎是一般性的结论。当涉及到纯虚拟函数时,编译器/链接器无法帮助我链接旧库。。令我惊讶的是——但我必须解决这个问题:——)
void main()
{
    A* a = A::Create();
    a->start();
    a->stop();
    a->write();
}