实例解析C++/CLI之接口与泛型

2023-10-27

实例解析C++/CLI 之接口与泛型
 
 
         接口
         某些时候,让不相关的类分享一组公有成员,以便产生相同的行为,是非常有用的。一个最基本的方法可能是通过一个公共的基类来定义它们,但这种方法太受局限,因为它要求这些类通过继承而互相关联,另外,它们也许还有着各自的基类,且CLI类型只支持单一类继承。
         C++/CLI提供了一种方法,可利用多个类实现一组通用的功能,这就是我们通称的“接口”,而一个接口则是一组成员函数的声明。要注意,这些函数只是声明,没有定义,也就是说,一个接口定义了一个由抽象函数组成的类型——这些函数实际上是纯虚函数,且在适当的时候,这些函数由客户类来实现。一个接口可允许不相关的类用同一名称和类型,实现同一功能,而无须要求这些类分享公共基类。在例1中演示了怎样定义一个接口。
 
例1:
using namespace System;
public interface class ICollection
{
        void Put(Object^ o);     //隐式public abstract
        Object^ Get();           //隐式public abstract
};
 
         一个接口的定义看上去非常像一个类,除了用interface取代了ref或value,所有的函数都没有函数体,且均隐式为public和abstract。按照通常的约定,一个接口名带有起始字母I,后再接一个大写字母。(接口类与接口结构是等价的。)与类相似,一个接口也能有public或private访问可见性。
 
         一个接口能有一个或多个“基接口”,在这种情况下,它将继承这些接口中的所有抽象函数,例如,在例2中,接口I2显式继承自I1,而I3显式继承自I1与I2,并通过I2隐式继承自I1。
 
例2:
interface class I1 { /* ... */ };
interface class I2 : I1 { /* ... */ };
interface class I3 : I1, I2 { /* ... */ };
 
         一个类可像从基类继承时那样,来实现一个接口,见例3。
 
例3:
public ref class List : ICollection
{
public:
    void Put(Object^ o)
    {
        // ...
    }
    Object^ Get()
    {
        // ...
    }
    // ...
};
 
         一个类能实现一个以上的接口,在这种情况下,必须使用逗号来分隔接口列表,顺序倒不是很重要。当然,一个类在实现一个或多个接口时,也能显式地带有一个基类,在这种情况下,基类通常(但不是必须)写在最前面。
         如果一个类实现了一个接口,但没有定义接口中所有的函数,这个类就必须声明为abstract。当然了,任何从抽象类继承而来的类也是抽象类,除非定义了之前的这些抽象函数。
         接口不提供多重继承,与此相比,一个CLI类也只能有一个基类,然而,接口却提供某种与多重类继承相似的功能,但概念与之完全不同,例如,一个类不能从接口中继承函数定义;接口继承体系是独立于类继承体系的——实现同一接口的类也许会、但也许不会通过类继承体系相互关联。
         例4演示了一个类:Queue,其与List无关联(但除了这个外,两者都是从Object继承而来的),两者都实现了同一接口。
 
例4:
public ref class Queue : ICollection
{
public:
    void Put(Object^ o)
    {
        // ...
    }
    Object^ Get()
    {
        // ...
    }
    // ...
};
 
         现在,可用它来编写处理参数为List或Queue的函数了,如例5。
 
例5:
ref class Item { /* ... */ };
void ProcessCollection(ICollection^ c);
int main()
{
    List^ myList = gcnew List;
    Queue^ myQueue = gcnew Queue;
    ProcessCollection(myList);
    ProcessCollection(myQueue);
}
void ProcessCollection(ICollection^ c)
{
    Item^ x = gcnew Item();
/*1*/    c->Put(x);
/*2*/    x = static_cast<Item^>(c->Get());
}
 
         在标号1与2中,为访问底层的List或Queue,使用了一个指向接口的句柄c,由此,你可传递给ProcessCollection一个指向任意对象的句柄,只要它的类实现了这个接口,或者它是从实现了这个接口的类继承而来的。
 
         例6演示了一个包含只读属性X、只写属性Y、读写属性Z的接口,对读写属性来说,get与set声明的顺序并不重要。
 
例6:
public interface class IProperties
 
{
    property int X { int get(); }
    property String^ Y { void set(String^ value); }
    property Object^ Z { Object^ get(); void set(Object^ value); }
};
 
         一个接口的成员,可以为静态数据成员、实例或静态函数、静态构造函数、实例或静态属性、实例或静态事件、操作符函数、或任意的嵌套类型。
 
         一般来说,我们会用for each语句来枚举集合中的所有元素,要对集合中的每个元素逐个进行操作,可使用如下语法:
 
for each (表达式形式的类型标识符)
   嵌入语句
 
         表达式类型必须为一个“集合类型”,如果要成为一个集合类型,这个类型必须实现接口System::Collections::IEnumerable,如例7中所定义。
 
例7:
public interface class IEnumerable
{
    IEnumerator^ GetEnumerator();
};
 
         正如大家所见,GetEnumerator返回一个指向IEnumerator的句柄,如例8中所定义。
 
例8:
public interface class IEnumerator
{
    bool MoveNext();
    void Reset();
    property Object^ Current { Object^ get(); }
};
 
         System::Array为一个集合类型,因为所有的CLI数组类型都继承自System::Array,所以,任何数组类型表达式都可以作为for each语句中的表达式。在例9的标号1中,for each用于遍历一个int数组,标号2中的处理过程也一样,但直接使用了枚举器。
 
例9:
using namespace System;
using namespace System::Collections;
int main()
{
        array<int>^ ary = gcnew array<int>{10, 20, 30, 40};
/*1*/    for each (int i in ary)
        {
            Console::Write(" {0}", i);
        }
        Console::WriteLine();
/*2*/    IEnumerator^ ie = ary->GetEnumerator();
        while (ie->MoveNext())
        {
            Console::Write(" {0}", static_cast<int>(ie->Current));
        }
        Console::WriteLine();
}
 
 
         泛型
         就像函数能用一个或多个类型表示符来定义一样,类型也可以这样来定义。假如有这样一种情况,某种类型建模了一个“数组”,其可使用下标来访问每个元素,这样的类型往往被称为“向量”,实现一个向量之后,可以保存一组int、一组double、或一组用户自定义类型的元素。然而,正是因为每种类型实现的代码对类型中的元素来说,都是唯一的,因此,可使用泛型机制来定义一个向量类型,并创建特定类型的实例。例10就是这样的一个例子。
 
例10:
generic <typename T>
public ref class Vector
{
    int length;
/*1*/    array<T>^ vector;
public:
   property int Length
    {
        int get() { return length; }
    private:
        void set(int value) { length = value; }
    }
/*2*/    property T default[int]
    {
        T get(int index) { return vector[index]; }
        void set(int index, T value) { vector[index] = value; }
    }
    Vector(int vectorLength, T initValue)
    {
        Length = vectorLength;
        vector = gcnew array<T>(Length);
        for (int i = 0; i < Length; ++i)
        {
/*3*/            this[i] = initValue;
        }
/*4*/        //for each (T element in vector)
        //{
        // element = initValue;
        //}
    }
    Vector(int vectorLength)
    {
        Length = vectorLength;
        vector = gcnew array<T>(Length);
        for (int i = 0; i < Length; ++i)
        {
/*5*/            this[i] = T();
        }
    }
    Vector()
    {
        Length = 0;
/*6*/        vector = gcnew array<T>(0);
    }
    ~Vector()       //多余的
    {
/*7*/        vector = nullptr;
    }
    virtual String^ ToString() override
    {
        String^ s = "[";
        int i;
        for (i = 0; i < Length - 1; ++i)
        {
/*8*/            s = String::Concat(s, this[i], ":");
        }
/*9*/        s = String::Concat(s, this[i], "]");
        return s;
    }
    virtual bool Equals(Object^ obj) override
   {
        if (obj == nullptr)
        {
            return false;
        }
        if (this == obj)    //在测试自身吗?
        {
            return true;
         }
/*10*/       if (GetType() == obj->GetType())
        {
            Vector<T>^ v = static_cast<Vector^>(obj);
            if (Length != v->Length) //是否向量有不同的长度?
            {
                return false;
            }
            for (int i = 0; i < Length; ++i)
            {
/*11*/               //if (this[i] != v[i])
                if (this[i]->Equals(v[i]) == false)
                {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
/*12*/ virtual int GetHashCode() override
    {
        return 0;
    }
};
 
         如同泛型函数一样,泛型的定义一般由generic <typename t1, ..., typename tn>打头,意思是通过tn引入了类型参数t1,这些参数的作用范围,可从类型定义的结束直到它们所依附的对象。在本例中,只有一个类型参数T。
 
         在标号1中可见,一个Vector是作为一个类型为T的元素数组存储的。
         在标号2中,定义了一个默认的索引属性,以便可用一个int下标值来访问一个Vector。当然了,在运行时,我们可以存取类型为T的元素,而不用管它实际上是什么类型。
         与其直接访问私有成员,倒不如通过公有属性来进行访问,比如说,用Length来取代length;使用下标来访问当前的Vector(标号3)时,我们使用了this[i]。在此,很有可能会想到使用for each循环来取代一般的老式for循环,如标号4,但是,在此使用for循环是行不通的。在for each循环中,通过命名在循环结构中的局部变量,可为每个元素都产生一个副本,也就是说,变量已经不是原来的元素了,因此,修改它的值不会改变元素的值。
         在标号5中,需要把每个元素设为默认值,幸运的是,标准C++要求每种类型都有一个默认的构造函数——甚至对不是类的类型也是这样,一般表示为类型名后紧跟空的圆括号。
         程序在构造函数没有参数的情况下(标号6),分配了一个零元素数组。(注意,指向零元素数组的句柄,不等同于包含nullptr的句柄。)这样做的目的是为了让成员函数可以正常工作,甚至对空Vector也是如此。
 
         为了完整起见,还定义了一个析构函数,以把句柄设为nullptr,目的是为了显式地告之垃圾回收器,我们对这个对象及与之关联内存的工作已经完成。
         使用在标号8及9中的this[i]还是真有点让人糊涂,那它真正的目的是什么呢?不像等价的模板类,泛型类Vector是在类型T未知的情况下编译为一个程序集,如果编译器不知道T的类型,它也不知道this[i]的类型,因此,它该怎样生成代码,才能把这个表达式转换为Concat所期望的类型呢?其实它不必知道,Concat的其中一个重载版本会要求它的第二个参数为Object^类型,且因为this[i]有类型T,无论类型T是否处在运行时,它都是从System::Object继承来的,因此,它与参数类型相兼容。更进一步来说,因为System::Object有一个名为ToString的虚函数,对此虚函数的调用将产生一个String^,假定类型T已覆盖了这个函数,那么就可返回正确的字符串了。
 
         函数Equals非常简单明了,但有一件事需要指出,请看标号11,从直觉上来说,我们一般会在此写成!=操作符,但是,这却通不过编译。请记住,类Vector是在对类型T一无所知的情况下编译的,除了它是继承自System::Object,同样地,唯一它允许对T调用的成员函数是那些由System::Object提供的函数,而这些类型未定义!=操作符,幸运的是,它提供了Equals函数,因此可使用它来达到同样的目的;接着,类型T覆盖了这个函数以执行对两个T的相等性判别,例11是主程序。
 
例11:
int main()
{
/*1*/    Vector<int>^ iv1 = gcnew Vector<int>(4);
/*2*/    Console::WriteLine("iv1: {0}", iv1);
/*3*/    Vector<int>^ iv2 = gcnew Vector<int>(7, 2);
    Console::WriteLine("iv2: {0}", iv2);
    iv2[1] = 55;
    iv2[3] -= 17;
    iv2[5] *= 3;
    Console::WriteLine("iv2: {0}", iv2);
/*4*/    Vector<String^>^ sv1 = gcnew Vector<String^>(3);
    Console::WriteLine("sv1: {0}", sv1);
/*5*/    Vector<String^>^ sv2 = gcnew Vector<String^>(5, "X");
    Console::WriteLine("sv2: {0}", sv2);
    sv2[1] = "AB";
    sv2[3] = String::Concat(sv2[4], "ZZ");
    Console::WriteLine("sv2: {0}", sv2);
/*6*/    Vector<DateTime>^ dv1 = gcnew Vector<DateTime>(2);
   Console::WriteLine("dv1: {0}", dv1);
/*7*/    Vector<DateTime>^ dv2 = gcnew Vector<DateTime>(3, DateTime::Now);
    Console::WriteLine("dv2: {0}", dv2);
    for (int i = 0; i < dv2->Length; ++i)
    {
        Thread::Sleep(1100);
        dv2[i] = DateTime::Now;
    }
    Console::WriteLine("dv2: {0}", dv2);
/*8*/    Vector<Vector<int>^>^ viv = gcnew Vector<Vector<int>^>(3);
    Console::WriteLine("viv: {0}", viv);
    viv[0] = gcnew Vector<int>(2, 1);
    viv[1] = gcnew Vector<int>(4, 2);
    viv[2] = gcnew Vector<int>(3, 5);
    Console::WriteLine("viv: {0}", viv);
/*9*/    Vector<int>^ iv3 = gcnew Vector<int>(4,3);
    Vector<int>^ iv4 = gcnew Vector<int>(4,3);
    Vector<int>^ iv5 = gcnew Vector<int>(4,2);
    Vector<int>^ iv6 = gcnew Vector<int>(5,6);
    Console::WriteLine("iv3->Equals(iv4) is {0}", iv3->Equals(iv4));
    Console::WriteLine("iv3->Equals(iv5) is {0}", iv3->Equals(iv5));
    Console::WriteLine("iv3->Equals(iv6) is {0}", iv3->Equals(iv6));
}
 
 
         为创建Vector的一个特定类型,可在尖括号中作为类型参数指定一个类型,如标号1、3所示。记住,int是值类System::Int32的同义词。(如果泛型有多个类型参数,需要以逗号把它们分隔开。)
         在标号4、5中,定义了一个String^类型的Vector——一个引用类型;在标号6、7中,定义了一个DateTime类型的Vector——一个值类型;在标号8中,定义了一个Vector,而其的元素则为int类型的Vector;最后,用不同的length及Vector int值测试了Equals函数,插1是程序的输出:
 
插1:例11的输出
 
iv1: [0:0:0:0]
iv2: [2:2:2:2:2:2:2]
iv2: [2:55:2:-15:2:6:2]
sv1: [::]
sv2: [X:X:X:X:X]
sv2: [X:AB:X:XZZ:X]
dv1: [1/1/0001 12:00:00 AM:1/1/0001 12:00:00 AM]
dv2: [4/9/2005 3:30:40 PM:4/9/2005 3:30:40 PM:4/9/2005 3:30:40 PM]
dv2: [4/9/2005 3:30:41 PM:4/9/2005 3:30:42 PM:4/9/2005 3:30:43 PM]
viv: [::]
viv: [[1:1]:[2:2:2:2]:[5:5:5]]
iv3->Equals(iv4) is True
iv3->Equals(iv5) is False
iv3->Equals(iv6) is False
 
 
         实际上,不但可以定义泛型类,还可以定义泛型接口与代理。
         在前面,也指出了调用泛型成员函数时的一些限制,默认情况下,一个类型参数被限定为从System::Object继承来的任意类型,也就是任意CLI类型。对泛型或函数中的类型参数,如果使用where子句,还可以施加一个或多个限定条件,见例12。
 
例12:
generic <typename T>
    where T : ValueType
public ref class Vector
{ ... };
value class C {};
 
/*1*/    Vector<int>^ iv;
/*2*/    Vector<String^>^ sv;        //错误
/*3*/  Vector<DateTime>^ dv;
/*4*/    Vector<Vector<int>^>^ viv; //错误
/*5*/    Vector<C>^ cv;
 
         在本例中,编译器将允许任意有着System::ValueType类型的类型参数,或从它继承来的类型被传递给泛型。假设此时又想定义某种特定的类型,如标号2和3所示,就会出错,因为String与Vector<int>不是值类型。同样地,如果换成例13中的限定条件,那么标号5就会被拒绝,因为值类型C没有实现接口System::IComparable,而System::Int32和System::DateTime却实现了。
 
例13:
generic <typename T>
   where T : ValueType
public ref class Vector, IComparable
{ ... };
 
         一旦编译器知道T可以被限定为比System::Object更明确的类型,就会允许调用这些类型中的成员函数,而这些类型则可包含一个基类型或任意顺序、任意数目的接口类型。
 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实例解析C++/CLI之接口与泛型 的相关文章

  • 在 C++ 中,当我将值传递给函数时,它是否总是转换为适当的类型?

    如果我有一个像这样的函数void func size t x 我称该函数为func 5 5 立即转换为size t类型 这通常适用于所有类型吗 我问这个问题是因为我发誓我见过人们编写代码 他们做类似的事情func 5 0 将 5 作为双精度
  • 如何将异常对象序列化为 xml 字符串

    我想要类似的东西 try code here catch Exception ex stringXML Exception toXML 这样 stringXML 的值就是
  • 沿着长数据序列在固定大小的移动窗口中查找中值

    给定一个数据序列 可能有重复项 一个固定大小的移动 窗口 从数据开始处每次迭代时移动窗口 序列 使得 1 从窗口中删除最旧的数据元素并添加新数据 元素被推入窗口 2 求每次移动时窗口内数据的中位数 以下帖子没有帮助 有效地找到随机序列的中值
  • Windows 10 UWP 中的视觉状态管理器未在页面加载时应用初始状态

    我有一个带有相关面板的页面 可以根据宽度重新组织 但是 除非宽度 gt 720px 否则它似乎不会在加载时应用任何状态 如果我在加载页面后调整页面大小 则两种状态都有效 解决方法是检查加载页面上的窗口大小并手动选择状态 但我相信这应该自动处
  • 为什么不能使用initializer_list来初始化unique_ptr的向量? [复制]

    这个问题在这里已经有答案了 我想知道为什么initializer list 不能与unique ptr 一起使用 std vector
  • Windows CE 6.0 和运行时链接到调试 DLL /MDd

    我在 x86 PC 上使用 Windows CE 6 0 R3 我已经为该平台构建了 NK bin 和 SDK 但我有一些问题需要了解如何使用 MTd 调试 DLL 构建控制台应用程序 如果我尝试构建这个 main c with MDd i
  • Visual Studio 2015 C# 找不到参考

    我在使用 Visual Studio 2015 和 C 时遇到了问题 在同一解决方案中添加对其他项目的引用时 Visual Studio 找不到所有类 例如 我创建了一个单元测试项目 我添加了对我创建的通信项目的引用 库中有 10 个类 但
  • 是否返回 std::move (x)?

    Are std vector
  • 我可以将特定警告视为错误吗?

    以下是我有时在学生代码中看到的模式的简化版本 bool foobar int a int b if a lt b return true 当然 真正的代码要复杂得多 Visual Studio 报告警告 C4715 并非所有控制路径都会返回
  • 在 C++ 中初始化指针

    可以在声明时将指针分配给值吗 像这样的东西 int p 1000 是的 您可以在声明时初始化指向值的指针 但是您不能这样做 int p 1000 是个地址运算符 并且您不能将其应用于常量 尽管如果可以 那会很有趣 尝试使用另一个变量 int
  • 二维数组的列求和

    我有一个IEnumerable
  • Docker 不遵循构建目录中的符号链接

    我正在对一个应用程序进行 Docker 化 其中涉及通过 Clang 将二进制文件与其他 C 文件链接 我们维护二进制文件的符号链接版本 因为它们在整个代码库中使用 我的 Docker 构建目录包含整个代码库 包括源文件以及这些源文件的符号
  • 函数中的重复参数检查

    我经常有调用层次结构 因为所有方法都需要相同的参数 如果我不想将它们放在实例级别 类的成员 那么我总是问我在每个方法中检查它们的有效性是否有意义 例如 public void MethodA object o if null o throw
  • std::iota 的 iota 代表什么?

    我假设 i 是增量 a 是分配 但我无法弄清楚或找到答案 而且 它看起来与非标准非常相似itoa我认为这很令人困惑 C iota is not an acronym or an initialism It is the word iota
  • 不兼容的指针到字符转换

    我正在编写一个程序 将卡片值写入 52 个点字符的多维数组中 该程序是一个测试数组 稍后我将其作为函数写入主程序中 在程序中 我通过以下方式初始化 for 循环计数0通过51 我用一个switch语句调制13将卡牌值分配给数组点 但是 我收
  • C++ 项目编译为静态库,编译为动态库失败(链接器错误)。为什么?

    我有一个 VS2008 本机 C 项目 我希望将其编译为 DLL 它仅引用一个外部库 log4cplus lib 并使用其功能 当然也使用 log4cplus 的 h 文件 当我尝试将我的项目编译为静态库时 它成功了 当我尝试作为 DLL
  • 使用 QTestLib 时抑制 qDebug

    我正在向 Qt 中的项目添加单元测试 并希望使用 QTestLib 我已经设置了测试并且它们运行良好 问题是在项目中我们重写了 qDebug 以输出到我们自己的日志文件 这在运行应用程序时效果很好 问题是当我测试类时 它有时会开始记录 然后
  • WPF DataGrid 选定项

    我有一个 DataGrid 用户可以通过在最后一行输入数据来添加项目 我还有一个按钮可以删除当前选定的项目 但是 当选择最后一行 空 用于添加新项目 时 最后选定的项目将保留在 SelectedItem 中 因此 如果我打开窗口 选择最后一
  • C# 中的快速字符串解析

    在 C 中解析字符串最快的方法是什么 目前我只是使用字符串索引 string index 并且代码运行合理 但我忍不住认为索引访问器所做的连续范围检查必须添加一些东西 所以 我想知道我应该考虑哪些技术来增强它 这些是我最初的想法 问题 使用
  • 频繁插入已排序的集合

    我已经对集合 列表 进行了排序 并且我需要始终保持其排序 我目前在我的集合上使用 List BinarySearch 然后在正确的位置插入元素 我也尝试过在每次插入后对列表进行排序 但性能不可接受 有没有一种解决方案可以提供更好的性能 也许

随机推荐

  • from tensorflow.examples.tutorials.mnist import input_data 出错

    在使用tensorflow实现辨别手写体的过程中遇到了一下错误 那么你则可以看下你当前环境下的TensorFlow的example中是否有tutorials文件或是否有example文件夹 进入后如果发现 没有则去tensorflow中进行
  • 用网线实现两台电脑之间的文件共享

    配置步骤 将一根网线分别插入两台电脑的网口 这个 没什么要说的吧 配置电脑IP 假设我们现在有两台电脑A B 我们想把电脑A上的某个文件或者文件夹共享到电脑B上 我们首先修改A的IP为192 168 0 1 如下图所示 同样的方法将电脑B的
  • cuda/cudnn/cuda 10.1安装教程

    方法1 NVIDIA 显卡驱动安装示例 ubuntu系统刚装好 推荐 Ubuntu 18 04 安装 NVIDIA 显卡驱动 ps 1 新系统的签名要重新注册 2 要禁用nouveau 新安装方法 其他参考 https zhuanlan z
  • windows安装jdk1.8并配置环境变量

    1 首先我们到官网 https www oracle com java technologies javase javase jdk8 downloads html下载安装包 提示要登录甲骨文账号 没有的话注册一个就好了 2 下载完成 我们
  • Hosting custom WPF calendar control in AX 2012

    原作者 https community dynamics com ax b axilicious archive 2013 05 20 hosting custom wpf calendar control in ax 2012 aspx
  • alter database 与 alter system的区别

    这两天一直在看oracle的教材 对于alter system和alter database的使用场合比较模糊 其实 在我的第一篇日记里边写了实例名 数据库名的区别 这两个命令区别就是做用范围的不同 alter database 主要是和数
  • k8s-工作负载组件理解

    先来段官方语言压压惊 工作负载是在 Kubernetes 上运行的应用程序 无论你的负载是单一组件还是由多个一同工作的组件构成 在 Kubernetes 中你 可以在一组 Pods 中运行它 在 Kubernetes 中 Pod 代表的是集
  • Flutter 返回键监听,提示再按一次退出app

    Flutter 返回键监听 提示再按一次退出app 直接贴代码 override Widget build BuildContext context return AnnotatedRegion
  • 服务器清理c盘日志文件,清理WIN2003服务器C盘垃圾的批处理

    保存为OOXX bat 然后运行即可 脚本会清理c盘下的日志 如有重要日志请先自行备份 ECHO OFF echo echo echo 清理几个比较多垃圾文件的地方 DEL F S Q C WINDOWS PCHealth ERRORREP
  • Python selenium 模拟操作下拉框

    学习笔记 from selenium import webdriver from selenium webdriver common by import By import time from selenium webdriver impo
  • B - Derangement

    题目链接 题解 用最少的改变两个数的位置使得a i i 题解 很简单 但是注意细节 下面试rte 2 的代码 include
  • 基础知识: HP-Unix下Oracle9i的安装

    基础知识 HP Unix下Oracle9i的安装 一 作为root用户的工作 1 配置内核参数 用root用户登陆 sam 进入system administrator manager 在其中选择kernel configuration 进
  • qt: exec()的用法,accept()和accepted的概念

    转载 http blog csdn net xdlichen article details 46374517 本篇 会重点讲述模式对话框 以及exec 的用法 accept 和accepted的概念 一 非模式对话框 非模式对话框是和同一
  • STM32-HAL 学习-TIM输入捕获-07

    1 时钟配置如前面 2 定时器输入捕获通道一设置 3 主函数 注意开启定时器中断 uint16 t capture 0 uint8 t End status 0 uint16 t Cap Timer 0 uint32 t H Timer 0
  • 刨根问底struts2

    MVC一探究竟之struts2 最近一直在学习JAVAEE中的MVC框架的一些知识 笔者写这篇博客的目的是想系统的对struts2一些核心使用的东西做一个总结 在myeclipse中构建好struts2框架之后 web容器当中的配置文件we
  • Keepalived 配置手册

    官网 https www keepalived org manpage html 1 描述 keepalived conf 是描述所有Keepalived关键字的配置文件 关键字放在块和子块的层次结构中 每一层由 和 对分隔 注释以 或 到
  • 目标检测中的回归损失函数系列二:IoU Loss

    IOU Loss 出自论文 https arxiv org pdf 1608 01471 pdf L1 和L2 loss是将bbox四个点分别求loss然后相加 并没有考虑靠坐标之间的相关性 而实际评价指标IOU是具备相关性 看一张图关注I
  • python实现-从带层级的json到markdown无序列表的父子关系的转换

    带层级的json到无序列表的父子关系的转换 从带层级的json到无序列表的父子关系的转换 总结 python中 with的用法一定要跟 as 结合在一起吗 顺便也说下 as 的用法吧 从带层级的json到无序列表的父子关系的转换 首先 我们
  • Timequest Timing Analyzer进行时序分析(二)

    四 用TimeQuest对DAC7512控制器进行时序分析 在对某个对象下时序约束的时候 首先要能正确识别它 TimeQuest会对设计中各组成部分根据属性进行归类 我们在下时序约束的时候 可以通过命令查找对应类别的某个对象 TimeQue
  • 实例解析C++/CLI之接口与泛型

    实例解析C CLI 之接口与泛型 接口 某些时候 让不相关的类分享一组公有成员 以便产生相同的行为 是非常有用的 一个最基本的方法可能是通过一个公共的基类来定义它们 但这种方法太受局限 因为它要求这些类通过继承而互相关联 另外 它们也许还有