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

时间:2016-03-03 19:01:36

标签: 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 ++共享库,其中包含一个实现“AImpl”+ A :: Create()函数(见下文):

A* A::Create {return new AImpl;}

class AImpl : public A
{
public:
    A() {}
    virtual ~A() {}

    virtual status_t start() {}
    virtual status_t stop()  {}
};

我构建共享库 - 没问题。 现在我在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()调用的实现。 即使在运行时,也不会发生崩溃或任何事情。看起来好像跳过了写调用。任何人都可以帮助解释 - 非常感谢: - )

谢谢 - 对于这个冗长的问题,我很难解释“单线”中的确切问题。

3 个答案:

答案 0 :(得分:1)

纯虚函数在链接过程中永远不会导致任何失败。相反,如果您尝试实例化抽象类型的对象,纯虚函数将导致编译错误。

提醒 - 抽象类型是一种类型,它具有(直接或间接通过继承)至少一个未被覆盖的纯虚函数。

答案 1 :(得分:0)

如果先前已构建解决方案,则可以编译或构建。这意味着它正在使用旧的目标代码。尝试清理您的解决方案,然后重建它。清理完解决方案后。然后尝试编译继承的类。另一件可能引起关注的事情是您已将继承的类声明为:

  

类AImpl:A {...};

我的问题是AImpl是如何从A继承的?您打算publicprotected还是private继承?

修改

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

答案 2 :(得分:0)

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