zoukankan      html  css  js  c++  java
  • CLI类的分类与定义 简单

    // CLI类的分类与定义.cpp: 主项目文件。
    /*
    C++/CLI中可以定义 两种类型的struct和class类型,
    一种为数值类(或数值结构):value class(value struct);
    一种是引用类(或引用结构):ref class(ref value)。
    与本地C++一样,class与struct的区别在于前者的成员默认为私有,后者默认为公有。
    下面仅以类来介绍,内容同样适用于结构。
    
    value class与ref class组成的是双关键字,也就是说,单独的value、ref并不是关键字。数值类与引用类的区别,以及它们与本地C++类的区别主要包括以下几个方面:
    
    1: 数值类的对象包含自己的数据,引用类的对象只能用句柄来访问。
    2: 在C++/CLI中,函数成员不能声明为const类型,取而代之的是字面值类型,修饰词关键字为 literal。
    3: 在非静态函数成员中,this指针类型与本地C++不同:数值类的this指针为内部指针类型(interior_ptr<T>),而引用类的this指针为句柄类型(T^)。
    4: C++/CLI类的数据成员不能包含本地C++数组或本地C++类对象。
    5: C++/CLI类无友元函数。
    6: C++/CLI类的数据成员不能包含位类型的数据成员。(什么是位数据类型)
    7: C++/CLI类的函数成员不能有默认的形参。
    此外,在C++/CLI中,不推荐类命名时使用前缀‘C’,其成员变量命名也不用前缀’m_’。
    */
    
    //一: 定义数值类
    
    #include "stdafx.h"
    #include <iostream>
    using namespace System;
    
    /*value class Height
    {
    private:
    	int feet;
    	int inches;
    	literial int inchesPerFoot = 12;
    	//literial 在C++/CLI是定义数据成员为常量的关键字
    
    	//利用字面值"literial来定义常量的一个缺点是:必须在定义常量的同时指定它的值,另外一种定义常量的方法是使用initonly修饰符"
    	//使用该修饰符的常量只能在构造函数的初始化表,或者构造函数内进行一次初始化,之后再也不能被修改,
    	//注意:不能在声明非静态initonly常量时指定初值,而必须是在构造函数的初始化表或构造函数体内,
    
    
    public:
    	//定认两种类型的构造函数
    	Height(int ins){
    	     //feet = ins/12;
    		 feet = ins / inchesPerFoot;
    		 //inches = ins% 12;
    		 inches = ins /inchesPerFoot;
    	}
    	Height(int ft, int ins):feet(ft), inches(ins){}
    
    	virtual String^ ToString() override
    	{
    	      return feet+L" feet " + inches+" inches";
    	}
    };*/
    
    /*value class Height
    {
    private:
    	int feet;
    	int inches;
    	//literial int inchesPerFoot = 12;
    	initonly int inchesPerFoot;
    	//literial 在C++/CLI是定义数据成员为常量的关键字
    	//利用字面值"literial来定义常量的一个缺点是:必须在定义常量的同时指定它的值,另外一种定义常量的方法是使用initonly修饰符"
    	//使用该修饰符的常量只能在构造函数的初始化表,或者构造函数内进行一次初始化,之后再也不能被修改,
    	//注意:不能在声明非静态initonly常量时指定初值,而必须是在构造函数的初始化表或构造函数体内,
    public:
    	//定认两种类型的构造函数
    	Height(int ins){
    	     //feet = ins/12;
    		 inchesPerFoot=12; 
    		 feet = ins / inchesPerFoot;
    		 //inches = ins% 12;
    		 inches = ins /inchesPerFoot;
    	}
    	Height(int ft, int ins):feet(ft), inches(ins)
    	{
    	     inchesPerFoot=12;    
    	}
    
    	virtual String^ ToString() override
    	{
    	      return feet+L" feet " + inches+" inches";
    	}
    };*/
    
    
    /*value class Height
    {
    private:
    	int feet;
    	int inches;
    	//literial int inchesPerFoot = 12;
    	//initonly int inchesPerFoot;
    	//literial 在C++/CLI是定义数据成员为常量的关键字
    	//利用字面值"literial来定义常量的一个缺点是:必须在定义常量的同时指定它的值,另外一种定义常量的方法是使用initonly修饰符"
    	//使用该修饰符的常量只能在构造函数的初始化表,或者构造函数内进行一次初始化,之后再也不能被修改,
    	//注意:不能在声明非静态initonly常量时指定初值,而必须是在构造函数的初始化表或构造函数体内,
    
    	//如果是静态的initonly变量,则只能在定义时指定初值,因为如果自构造函数中定义,则每次创建实例都将对静态变量赋值
    	//这显然与静态,常量这样的冲突,解决的办法是,如果一定要在构造函数中初始化initonly类型的静态变量,则可定义一个静态构造函数
    
    	static Length(){ inchesPerFoot = 12; }
    	//静态构造函数没有形参,且没有初始化表,总是被声明为provate,它不能被直接调用,而是由普通构造函数在调用之关自动调用
    	//这种方法与在定义静态initonly变量时指定初始化值的唯一区别是,初始化值可以是运行时确定的
    
    
    public:
    	//定认两种类型的构造函数
    	initonly static int inchesPerFoot;
    
    
    	Height(int ins){
    	     //feet = ins/12;
    		 //inchesPerFoot=12; 
    		Height::Length();
    		 feet = ins / inchesPerFoot;
    		 //inches = ins% 12;
    		 inches = ins /inchesPerFoot;
    	}
    	Height(int ft, int ins):feet(ft), inches(ins)
    	{
    	     //inchesPerFoot=12;  
    		Height::Length();
    	}
    
    	virtual String^ ToString() override
    	{
    	      return feet+L" feet " + inches+" inches";
    	}
    };*/
    //上面的实例失败
    
    
    
    /*int main(array<System::String ^> ^args)
    {
    	//Height::Length();
    	Height myHeight = Height(6,3);
    	Height^ yourHeight = Height(70);
    	Height hisHeight = *yourHeight;
    
    	Console::WriteLine(L"My height is {0}", myHeight);
    	Console::WriteLine(L"Your height is {0}", yourHeight);
    	Console::WriteLine(L"His height is {0}", hisHeight);
    	
    	double pi = 3.142;
    	//double类型被映射到System命名空间中的System::Double类,该类实现了ToString方法,因此可以正确的输出变量pi的数值3.142而非类名Double
    
    	Console::WriteLine(pi.ToString());
    
        system("pause");
        return 0;
    }*/
    /*
    在上面的例子中,myHeight和hisHeight被分配在堆栈 上,yourHeight被分配到了CLR堆上。其中hisHeight是yourHeight的一个副本,当向 hisHeight赋值时,需要用*操作符对句柄yourHeight进行解除引用计算。这是因为数值类对象总是包含自己的数据,因此它们不能引用同一个对象,在赋值时总是采用复制的方式进行。注意:在C++/CLI中,不能重写默认构造函数。默认构造函数将所有的值类型数据成员初始化为0,将引用类型(句柄)初始化为nullptr。同样,也不能重载复制构造函数和赋值操作符。默认的复制操作是将每一个数据成员进行复制,对象间的赋值也是如此。
    
    C++/CLI中的类都有一个成员函数ToString(),它返回一个表示对象的字符串 句柄。默认情况下,该字符串为类名。这从上面的输出可以看出:传递给WriteLine()函数的是Height对象,结果输出的并非对象所包含的高度 值,而是类名Height,这是因为编译器认为此处需要调用该对象的字符串表示法,因此安排的ToString()函数调用,这个过程可以显示的表达为
    */
    
    
    
    //二 定义引用类
    //引用类更加类似于本地C++类,它没有数值类那么多的限制,但是引用类没有默认的复制构造函数和赋值运算符
    //如果定义的类需要进行复制或赋值,必须显式地添加相应的函数成员,下面的例子定义了一个引用类及其使用方法
    
    ref class Box
    {
    public:
    	Box():Length(1.0), Width(1.0), Height(1.0)
    	{
    	
    	}
    
    	Box(double lv, double wl, double hl):Length(lv), Width(wl), Height(hl)
    	{
    	
    	}
    
    	double Volume()
    	{
    	    return Length*Width*Height;
    	}
    private:
    	double Length;
    	double Width;
    	double Height;
    };
    
    
    int main(array<System::String ^> ^args)
    {
    
    	Box^ aBox;
    	Box^ newBox = gcnew Box(10, 15, 20);
    	aBox = gcnew Box;
    
    	Console::WriteLine(L"Default box volume is {0}", aBox->Volume());
    	Console::WriteLine(L"New Box volume is {0}", newBox->Volume());
    
        system("pause");
        return 0;
    }
    //在上面的例子中,main()函数的第一句没有创建任何对象,仅仅声明了一个句柄,并被默认的赋值成nullptr。此外,引用对象总是在堆上创建,因此总是用gcnew来调用其构造函数,并用句柄来跟踪引用对象。
    

      

  • 相关阅读:
    第十六天
    第十五天
    STM8L段式液晶驱动器
    STM8L的LCD接口详解及驱动程序
    作为合格的工程师,这些电路图一辈子都得记住!
    双向晶闸管触发电路工作原理图
    3~15伏10A大电流可调稳压电源
    用TL431制作简单充电器电路
    5V USB充电器电路图
    555
  • 原文地址:https://www.cnblogs.com/xiangxiaodong/p/2752910.html
Copyright © 2011-2022 走看看