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

C++ shared library: Pure virtual function does not cause link error

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

这是一个接口定义:

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

我构建共享库 - 没问题。 现在我在 Class 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();
}

现在我明白上面的编译,但我认为它会失败 linking,因为共享库中没有 write() 调用的实现。 即使在 运行 时间,也没有崩溃或任何事情发生。似乎跳过了 write 调用。任何人都可以帮助解释 - 将不胜感激:-)

谢谢 - 很抱歉这个冗长的问题,我很难在 "single liner"..

中解释确切的问题

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

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

如果之前已经构建了解决方案,这可能会编译或构建。这意味着它正在使用旧的目标代码。尝试干净地构建您的解决方案,然后重新构建它。一旦你的解决方案被清理干净。然后尝试编译继承的class。另一件可能值得关注的事情是,您已将继承的 class 声明为:

class AImpl : A { ... };

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

编辑

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

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