【问题标题】:C++ CLI dynamic_cast and multiple inheritance (Windows Forms and Interfaces)C++ CLI dynamic_cast 和多重继承(Windows 窗体和接口)
【发布时间】:2012-07-06 08:33:13
【问题描述】:

我正在使用的场景如下所示:

public interface INativeWindow { ... }

是一种本机窗口类型的界面,包含一些必需的基本方法来实现,以便获得最小的窗口支持(例如最小化、恢复等)。这是属于接口项目的 C# 接口。

现在我想在CLINativeWindow c++-cli 类中实现它:

public ref class CLINativeWindow: public SWF::NativeWindow, INativeWindow
{ 
 ...
}

最后,我有另一个ref c++ cli 类,它有一个CLINativeWindow 类型的内部成员和一个返回INativeWindow^ 句柄的包装属性:

virtual property INativeWindow^ OwnNativeWindow
                {
                    INativeWindow^ __clrcall get() sealed { return NativeWindow;}
                    void __clrcall set(INativeWindow^ value) { NativeWindow = dynamic_cast<CLINativeWindow^>(value);}
                }

这里的问题是dynamic_cast 不起作用,属性的getter 方法的隐式多态向下转换也不起作用。如果我没有被误导,我想我在 C++ 中使用 normal 指针的几个地方读到过,这样的错误确实有效。现在,SWF::NativeWindow 是经典的 windows 窗体原生窗口类(对无意的头韵表示抱歉),它应该有一个虚拟方法,就像接口一样,所以动态转换运算符没有问题,因为多态继承是涉及。我错了还是这在 dotNet C++ CLI 中完全不可能?

编辑 附加代码:

public ref class ExampleForSO
{
  CLINativeWindow^ NativeWindow;


 virtual property INativeWindow^ OwnNativeWindow
                    {
                        INativeWindow^ __clrcall get() sealed { return NativeWindow;}
                        void __clrcall set(INativeWindow^ value) { NativeWindow = dynamic_c

ast<CLINativeWindow^>(value);}
            }
}

错误来自编译时,它们指出不能对 getter 和 setter 执行转换/强制转换(即不能从 B^ 转换为 A^ 以及从 B^ 转换为 A^).. 更新 如果类位于不同的文件中,则无法在标头中实现该属性。在单独的.cpp 源文件中实现它不会再导致编译时错误,并且可以正常工作。

【问题讨论】:

    标签: c# winforms dynamic c++-cli multiple-inheritance


    【解决方案1】:

    这里没有多重继承。您的CLINativeWindow 继承自一个类:SWF::NativeWindow,它还实现了INativeWindow 接口。

    您没有提供足够的信息(您遇到什么错误?可以粘贴到 VS 中以重现问题的示例代码?),但总的来说,您发布的代码没有任何问题。

    我的猜测是您的NativeWindow 被声明为:

    CLINativeWindow NativeWindow;
    

    没有急需的^。尝试将其声明为:

    CLINativeWindow^ NativeWindow;
    

    编辑

    以下内容为我编译干净:

    public interface class INativeWindow
    {};
    
    public ref class SWFNativeWindow
    {};
    
    public ref class CLINativeWindow : SWFNativeWindow, INativeWindow
    {};
    
    public ref class NWHolder
    {
    public:
        virtual property INativeWindow^ OwnNativeWindow
        {
            INativeWindow^ __clrcall get() sealed { return nativeWindow_; }
            void __clrcall set(INativeWindow^ w) { nativeWindow_ = dynamic_cast<CLINativeWindow^>(w); }
        }
    
    private:
        CLINativeWindow^ nativeWindow_;
    };
    

    【讨论】:

    • 我确实在类型中包含了句柄说明符。我认为在 C++-CLI 中没有“实现接口”这样的概念,它类似于 C++ 的“继承抽象类”习语。这就是我在标题中指定多重继承的原因。此外,是否可以使用dynamic_cast 运算符将实现类转换为其interface 句柄......何时......派生类也继承另一个类?这是主要问题,从我在互联网上找到的内容我一无所知。谢谢!
    • 感谢更新,而不是 SWFNativeWindow ref 类,您可以尝试:System::Windows::Forms::NativeWindow 代替吗?应该没问题,因为WndProc 是一个虚拟保护方法。但对我来说,情况并非如此。
    • 感谢您提供模型代码。这正是我正在谈论的说明性场景,除了一点点区别:我使用的是System::Windows::Forms::NativeClass,而SWF 只是一个命名空间别名。在这种情况下,演员阵容失败(但它应该像为你所做的那样工作)。此外,我认为要使强制转换与多态性一起使用,基类中至少需要一个虚拟方法。
    • 即使使用System::Windows::Forms::NativeWindow 仍然可以为我编译。尝试在此处编译示例代码,然后与您拥有的实际代码进行比较。至于dynamic_cast,您所说的对于C++ 是正确的。但是,对于 C++/CLI 中的托管类型,dynamic_cast 等效于 C# as 关键字。
    • 谢谢,我试过了,它也可以为我编译,没有任何问题,但是在一个空的项目中,在主 cpp 文件中。我想问题出在其他地方。
    猜你喜欢
    • 1970-01-01
    • 2022-08-12
    • 1970-01-01
    • 2018-04-30
    • 2011-07-31
    • 1970-01-01
    • 2012-06-10
    • 2021-08-10
    • 2013-12-06
    相关资源
    最近更新 更多