zoukankan      html  css  js  c++  java
  • 托管C++笔记(一)原创

    最近前一个项目结束,新的项目还未开始,并且下一个项目有可能需要用到C#/C++混合编程,于是乎开始了托管C++的学习过程。现在公司的游戏编辑器就是采用了C#做编辑器,C++做游戏引擎,托管C++做封装连接编辑器和引擎。不可否认.NET的功能强大,个人现在也偏好使用C#做工具。不过之前托管C++从未接触,想来凭借多年C++的底子和C#的经验,学习托管C++应该也不是件难事。

    学习教材:Visual C++ .NET 托管扩展编程中文版,PDF扫描版,很不清晰………………勉强能看。

    看完第一章,并经过动手试验以后发现书本上讲的很多东西已经过时了,我使用的环境是Visual Studio .NET 2005/2008,而教程应该是基于.NET 2003写的。

    很多关键字已经在.NET 2005中更改过,具体更新列表可以参考mdsn或者点击这里

    几个最基础的也是最重要的更新:

    __gc class改成了ref class

    __property 改成了 property

    __abstract  改成了 abstract

    __gc __interface 改成了 interface class

    __event 改成了 event

    不难看出来,这些改动只是把前面的下滑线去掉了。不过这只是字面上的改动

    • property的格式改成跟C#类似了

    之前的格式是

    __property void set_Name(String^ name);

    __property String^ get_Name();

    在2005里面变成了

    property String^ Name
    {
        String
    ^ get()
        {
            
    return mName;
        }
        
    void set(String^ name)
        {
            mName 
    = name;
        }
    }

    对于熟悉C#的人来说是一个非常不错的改进。

    • abstract改动让我很无语:

    __abstract变成abstract以后,还必须放在类名字后面

    原来的格式

    __gc __abstract class Test : public Base
    {
    }

    新的格式

    ref class Test abstract : public Base
    {
    }
    • 空指针的判断

    不再使用0或者null来判断指针是否为空了,而是用nullptr

    • new操作符的改动

    因为托管类必须要在托管堆上分配,否则会引起错误。所以在旧版本里面要使用__gc new来创建实例,但是也允许直接new。这个有可能会造成误会。

    新的版本里面,所有的托管类必须要用gcnew来创建实例,否则会产生编译错误

    • interface的实现必须使用virtual关键字

    这跟旧版本有些区别,书上的范例:

    __gc __interface IPrint

    {
        
    void Print();
        __event OnPrinted
    * printed;
    }

    __delegate 
    void OnPrinted(String*);

    __gc 
    class PrintedDoc : public IPrint
    {
    public:
        
    void Print()
        {
        }
        __event 
    virtual OnPrinted* printed
    }

    旧版本只有成员才需要在实现的时候使用virtual,而方法没有要求。

    但是在新版本里面必须要使用virtual,包括方法

    下面是我做的一个测试

    public interface class TestInterface
    {
        
    event CallMethod^ TestEvent;
        property String
    ^ Name
        {
            String
    ^ get();
            
    void set(String^ name);
        }
        
    void TestFunc();
    }

    ref class Test : public TestInterface
    {
    public:
        
    virtual event CallMethod^ TestEvent;
        property String
    ^ Name
        {
            
    virtual void set(Strin^ name)
            {
                mName 
    = name;
            }
            
    virtual String^ get()
            {
                
    return mName;
            }
        }

        
    virtual void TestFunc()
        {
        }
    protected:
        String
    ^ mName;
    }

    这里的interface class让我很困惑,为什么一定要加class,难道还可以用interface struct?

    如果在实现类里面没有使用virtual,编译器会报错。另外补充一点,如果有派生类需要重写基类的虚方法,必须使用override,否则编译器报错

    范例如下:

    ref class Derived : public Test
    {
    public:
        
    virtual void TestFunc() override
        {
            __super::TestFunc();
        }
    }

    这里出现了__super关键字,跟C#的base和Java里面的super类似,通常在C++里面要调用基类的方法,我们都是采用Test::TestFunc()的形势,而且你也可以调用更上层的方法。而__super则限定了只能是直接基类的方法。

    • 奇妙的实现

    .NET里面只允许单继承,也就是所有托管类只能有一个托管基类。

    如果某个派生类实现了某个接口,但是没有提供实现方法,不过该派生类的基类有一个完全匹配实现,这个实现会被当成是接口的实现。

    范例:

     

    public interface class TestInterface
    {
        
    void TestFunc();
    }

    ref class TestFuncClass
    {
    public:
        
    virtual void TestFunc()
        {
        }
    }

    ref class Test : public TestFuncClass, public TestInterface
    {
    }

    上面的代码是可以编译通过的

    • 托管类可以delete

    delete会调用该类的析构函数,但是该对象仍然存在于托管堆中,依然是有效的,只是析构里面可能更改了对象的状态,导致潜在的问题。

    • 托管C++里的event不需要判断是否为空指针

    很神奇的发现这一点,在C#里面必须得检查这个event是否有人监听,否则直接触发这个事件会造成运行出错。

    if (null != TestEvent)
    {
        TestEvent(....);
    }
    但是同样的代码放在托管C++里面反而会报编译错误。
  • 相关阅读:
    支持对所有文件格式的收集、同一画面编辑和关联等管理
    [转]养成好习惯是做好个人知识管理根本之道
    小心你的QQ聊天记录毁于一旦
    如果开源,服务又不一定找开发商,完全可以找更便宜就近的第三方
    不要使用没有升级保证的PKM软件
    针式PKM V5.78
    关于在英文Windows XP 企业版下运行出现乱码,甚至无法打开数据库的错误处理方法
    [收藏]你经常遇到如下困境吗
    个人资源管理的时代,已经到来,你意识到了吗?
    [转]针对文献管理软件Note谈我心目中的个人资源信息管理软件
  • 原文地址:https://www.cnblogs.com/hyamw/p/1857362.html
Copyright © 2011-2022 走看看