如何解决“Delphi样式类必须从Delphi样式类派生”?

Yan*_*hon 2 c++ delphi c++builder

如果我有一个类定义为:

// foo.h
class Foo
{
public:
    virtual void GetFoo();
}
Run Code Online (Sandbox Code Playgroud)

我想要一个TForm继承它,例如

class TFMainWindow : public TForm, public Foo
{
   ...
}
Run Code Online (Sandbox Code Playgroud)

我收到错误

[bcc32c 错误] TFMainWindow.h(36):Delphi 样式类必须从 Delphi 样式类派生

我该如何解决这个问题?

Rem*_*eau 5

TForm派生自TObject,它是一个“Delphi 风格的类”,即它是在 Delphi pascal 中实现的,而不是在 C++ 中实现的。在Delphi中,TObject是所有类对象实例的根。

Delphi 不像 C++ 那样支持类的多重继承。只有单一继承。一个 Delphi 类最多只能有 1 个基类。但是,它可以实现多个接口

因此,在 C++Builder 中,当 C++ 类作为TObject祖先时,任何其他非基祖先必须只是接口,而您的Foo不是。在这种情况下,接口是任何没有数据成员的类,并且只允许使用纯虚方法和声明。__property

如果Foo::GetFoo()纯虚拟方法,那么您的代码将按预期工作,例如:

class Foo
{
public:
    virtual void GetFoo() = 0;
};

class TFMainWindow : public TForm, public Foo
{
    ...
public:
    void GetFoo();
    ...
};
Run Code Online (Sandbox Code Playgroud)

这只是 C++ 和 Delphi 相互交互方式的限制。

这是有记录的行为:

C++ 和 Delphi 类模型:继承和接口

与 C++ 不同,Delphi 语言不支持多重继承。您创建的任何具有 RTL 祖先的类都会继承此限制。也就是说,您不能对 Delphi 风格的 C++ 类使用多个基类,即使 RTL 类不是直接祖先。

使用接口代替多重继承

对于在 C++ 中使用多重继承的许多情况,Delphi 代码会使用接口。没有直接映射到 Delphi 接口概念的 C++ 结构。Delphi 接口就像一个没有实现的类。也就是说,接口就像一个类,其中所有方法都是纯虚拟的,并且没有数据成员。虽然 Delphi 类只能有一个父类,但它可以支持任意数量的接口。Delphi 代码可以将类实例分配给任何这些接口类型的变量,就像它可以将类实例分配给任何祖先类类型的变量一样。这允许共享相同接口的类的多态行为,即使它们没有共同的祖先。

在 C++Builder 中,编译器将仅具有纯虚方法且没有数据成员的类识别为与 Delphi 接口相对应。因此,当您创建 Delphi 样式类时,您可以使用多重继承,但前提是除 RTL 或 Delphi 样式类之外的所有基类都没有数据成员且只有纯虚方法。

注意:接口类不需要是Delphi风格的类;唯一的要求是它们没有数据成员,只有纯虚方法。

Delphi 和 C++ 之间对象模型的差异也是为什么派生的 C++ 类TObject 必须使用 来在动态内存中构造的new原因,尽管 C++ 通常允许在静态/自动内存中构造类而不使用new