zoukankan      html  css  js  c++  java
  • 友元函数和友元类

    友元函数和友元类

    采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义 一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称 为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类 的私有成员。

    友元函数
    友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,其格式如下:
    friend 类型 函数名(形式参数);

    友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。
    一个函数可以是多个类的友元函数,只需要在各个类中分别声明。
    友元函数的调用与一般函数的调用方式和原理一致。
    友元类
    友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员)。
    当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。定义友元类的语句格式如下:
    friend class 类名;
    其中:friend和class是关键字,类名必须是程序中的一个已定义过的类。

    例如,以下语句说明类B是类A的友元类:
    class A
    {

    public:
    friend class B;

    };
    经过以上说明后,类B的所有成员函数都是类A的友元函数,能存取类A的私有成员和保护成员。

    使用友元类时注意:
    (1) 友元关系不能被继承。
    (2) 友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

    (3) 友元关系不具有传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明

    友元函数

    特点

    友元函数是能够访问类中的私有成员的成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样。 友元关系不具对称性。即 A 是 B 的友元,但 B 不一定是 A 的友元。 友元关系不具传递性。即 B 是 A 的友元,C 是 B 的友元,但是 C 不一定是 A 的友元。 作用及特点 友元提供了不同类的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制。通过友元,一个不同函数或另一个类中的成员函数可以访问类中的私有成员和保护成员。c++中的友元为封装隐藏这堵不透明的墙开了一个小孔,外界可以通过这个小孔窥视内部的秘密。友元的正确使用能提高程序的运行效率,但同时也破坏了类的封装性和数据的隐藏性,导致程序可维护性变差。

    应用实例

    下面举一例子说明友元函数的应用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    #include<iostream>
    #include<cmath>
    using namespace std;
    class Point
    {
    public:
        Point(double xx, double yy)
        {
            x=xx;
            y=yy;
        };
        void Getxy();
        friend double Distance(Point &a, Point &b);
    private:
        double x, y;
    };
    void Point::Getxy()
    {
        cout<<"("<<x<<","<<y<<")"<<endl; }="" double="" distance(point="" &a,="" point="" &b)="" {="" dx="a.x" -="" b.x;="" dy="a.y" b.y;="" return="" sqrt(dx*dx+dy*dy);="" int="" main(void)="" p1(3.0,="" 4.0),="" p2(6.0,="" 8.0);="" p1.getxy();="" p2.getxy();="" d="Distance(p1," p2);="" cout="" <<="" "distance="" is"="" endl;="" 0;="" }<="" pre=""><br>
    说 明:在该程序中的Point类中说明了一个友元函数Distance(),它在说明时前边加friend关键字,标识它不是成员函数,而是友元函数。它的 定义方法与普通函数定义一样,而不同于成员函数的定义,因为它不需要指出所属的类。但是,它可以引用类中的私有成员,函数体中 a.x,b.x,a.y,b.y都是类的私有成员,它们是通过对象引用的。在调用友元函数时,也是同普通函数的调用一样,不要像成员函数那样调用。本例 中,p1.Getxy()和p2.Getxy()这是成员函数的调用,要用对象来表示。而Distance(p1,
     p2)是友元函数的调用,它直接调用,不需要对象表示,它的参数是对象。(该程序的功能是已知两点坐标,求出两点的距离。)<br>
    <p></p>
    <p></p>
    <h2 class="headline-1">
    3友元类</h2>
    <p></p>
    <p></p>
     
    友元除了前面讲过的函数以外,友元还可以是类,即一个类可以作另一个类的友元。当一个类作为另一个类的友元时,这就意味着这个类的所有成员函数都是另一个类的友元函数。
     
    让我们回顾一下重载的“等于操作符的”定义,它是为名字空间域中定义的String 类而提供的,针对两个String 对象的“等于操作符”如下:
     
     
    <table border="0" cellpadding="0" cellspacing="0">
    <tbody>
    <tr>
    <td class="gutter">
     
    1
     
    2
     
    3
     
    4
     
    5
     
    6
    </td>
    <td class="code">
     
     
    <code class="cpp color1 bold">bool</code><code class="cpp plain">operator==(
    </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     &str1, </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     &str2 )</code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">if</code><code class="cpp plain">(
     str1.size() != str2.size() )</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">return</code><code class="cpp keyword bold">false</code><code class="cpp plain">;</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">return</code><code class="cpp functions bold">strcmp</code><code class="cpp plain">(
     str1.c_str(), str2.c_str() ) ? </code><code class="cpp keyword bold">false</code><code class="cpp plain">:
    </code><code class="cpp keyword bold">true</code><code class="cpp plain">;</code>
     
    <code class="cpp plain">}</code>
     
    </td>
    </tr>
    </tbody>
    </table>
     
     
     
    把这个定义与被定义为成员函数的操作符定义相比较:
     
     
    <table border="0" cellpadding="0" cellspacing="0">
    <tbody>
    <tr>
    <td class="gutter">
     
    1
     
    2
     
    3
     
    4
     
    5
     
    6
    </td>
    <td class="code">
     
     
    <code class="cpp color1 bold">bool</code><code class="cpp plain">String::operator==(
    </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     &rhs ) </code><code class="cpp keyword bold">const</code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">if</code><code class="cpp plain">(
     _size != rhs._size )</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">return</code><code class="cpp keyword bold">false</code><code class="cpp plain">;</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">return</code><code class="cpp functions bold">strcmp</code><code class="cpp plain">(
     _string, rhs._string ) ? </code><code class="cpp keyword bold">false</code><code class="cpp plain">:
    </code><code class="cpp keyword bold">true</code><code class="cpp plain">;</code>
     
    <code class="cpp plain">}</code>
     
    </td>
    </tr>
    </tbody>
    </table>
     
     
     
    你看到区别了吗?我们注意到必须要修改函数定义内部对于String 类私有数据成员的引用方式。因为新的等于操作符是全局函数,不是类成员函数,它不能直接引用String
     的私有数据成员,它使用访问成员函数size()和c_str()来获得String
     对象的大小,以及底层的C 风格字符串。
     
    另外一种可能的实现是把全局“等于操作符”声明为String 类的友元friend。通过把函数或操作符声明为友元,一个类可以授予这个函数或操作符访问其非公有成员的权利。
     
    友元声明以关键字friend 开始,它只能出现在类定义中。因为友元不是授权类的成员,所以它不受其所在类的声明区域public private protected 的影响。这里我们选择把所有友元声明组织在一起并放在类头之后:
     
     
    <table border="0" cellpadding="0" cellspacing="0">
    <tbody>
    <tr>
    <td class="gutter">
     
    1
     
    2
     
    3
     
    4
     
    5
     
    6
     
    7
     
    8
    </td>
    <td class="code">
     
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">String
    </code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">friend</code><code class="cpp color1 bold">bool</code>
    <code class="cpp plain">
    operator==( </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     &, </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     & );</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">friend</code><code class="cpp color1 bold">bool</code>
    <code class="cpp plain">
    operator==( </code><code class="cpp keyword bold">const</code><code class="cpp color1 bold">char</code>
    <code class="cpp plain">
    *, </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     & );</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">friend</code><code class="cpp color1 bold">bool</code>
    <code class="cpp plain">
    operator==( </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     &, </code><code class="cpp keyword bold">const</code><code class="cpp color1 bold">char</code>
    <code class="cpp plain">
    * );</code>
     
    <code class="cpp keyword bold">public</code><code class="cpp plain">:</code>
     
    <code class="cpp spaces">    </code><code class="cpp comments">//
     ... String 类中的其他部分</code>
     
    <code class="cpp plain">};</code>
     
    </td>
    </tr>
    </tbody>
    </table>
     
     
     
    String 类中的三个友元声明把全局域中声明的三个重载的“比较操作符”(在上节介绍)声明为String 类的友
     
    元既然这些等于操作符已经被声明为友元那么它们的定义就可以直接引用String 的私有成员了。
     
     
    <table border="0" cellpadding="0" cellspacing="0">
    <tbody>
    <tr>
    <td class="gutter">
     
    1
     
    2
     
    3
     
    4
     
    5
     
    6
     
    7
     
    8
     
    9
     
    10
     
    11
     
    12
     
    13
    </td>
    <td class="code">
     
     
    <code class="cpp comments">//
     friend 操作符直接引用 String 的私有成员</code>
     
    <code class="cpp comments">//
     friend operators: refer to String private members directly</code>
     
    <code class="cpp color1 bold">bool</code><code class="cpp plain">operator==(
    </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     &str1, </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     &str2 )</code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">if</code><code class="cpp plain">(
     str1._size != str2._size )</code>
     
    <code class="cpp spaces">        </code><code class="cpp keyword bold">return</code><code class="cpp keyword bold">false</code><code class="cpp plain">;</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">return</code><code class="cpp functions bold">strcmp</code><code class="cpp plain">(
     str1._string, str2._string ) ? </code><code class="cpp keyword bold">false</code><code class="cpp plain">:
    </code><code class="cpp keyword bold">true</code><code class="cpp plain">;</code>
     
    <code class="cpp plain">}</code>
     
    <code class="cpp keyword bold">inline</code><code class="cpp color1 bold">bool</code>
    <code class="cpp plain">
    operator==( </code><code class="cpp keyword bold">const</code><code class="cpp plain">String
     &str, </code><code class="cpp keyword bold">const</code><code class="cpp color1 bold">char</code>
    <code class="cpp plain">
    *s )</code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">return</code><code class="cpp functions bold">strcmp</code><code class="cpp plain">(
     str._string, s ) ? </code><code class="cpp keyword bold">false</code><code class="cpp plain">:
    </code><code class="cpp keyword bold">true</code><code class="cpp plain">;</code>
     
    <code class="cpp plain">}</code>
     
    <code class="cpp comments">//
     以下略</code>
     
    </td>
    </tr>
    </tbody>
    </table>
     
     
     
    <h3 class="headline-2">
    如何判断是类的友元</h3>
     
    有 人可能会说在这种情况下由于c_str()和size()是内联的它们提供了等价的效率,并且保留了成员封装所以没必要直接访问_size 和_string ,这是对的。使用成员访问函数而不是直接访问成员,并不总是意味着它的效率较低。由于存在这些访问函数,所以没有必要把等于操作符声明为String
     类的友元。
    那 么我们怎样判断一个非类成员的操作符应该是类的友元还是应该使用成员访问函数呢?一般来说,类的实现者应该尽量使得名字空间函数和访问类内部表示的操作符 的数目最小化。如果已经提供了访问成员函数并且它们具有等同的效率那么最好是使用这些成员函数,并且把名字空间操作符与类表示中的变化隔离开。但是如果类 的实现者决定不为该类的某些私有成员提供访问成员函数,而且名字空间操作符需要引用这些私有成员才能完成它们的操作,那么就必须使用友元机制。
    友元声明的最常见用法是允许非成员的重载操作符访问一个视其为朋友的类的私有成员。原因是除了提供左和右操作数的对称性外,可使非成员的重载操作符就像成员函数一样能够完全访问一个类的私有成员。
    虽然友元声明的主要用处是在重载操作符上,但是在某些情况下一个名字空间函数,另一个在此之前被定义的类的成员函数或者一个完整的类必须声明为友元。
    在使一个类成为另一个类的友元时,友元类的成员函数,被赋予访问授权类的非公有成员的权利。
    下面我们将更详细地了解函数而不是操作符的友元声明。
    一个类必须把它希望与之建立友元关系的重载函数集中的每个函数都声明为友元。
    例如
     
     
    <table border="0" cellpadding="0" cellspacing="0">
    <tbody>
    <tr>
    <td class="gutter">
     
    1
     
    2
     
    3
     
    4
     
    5
     
    6
     
    7
     
    8
     
    9
    </td>
    <td class="code">
     
     
    <code class="cpp keyword bold">extern</code><code class="cpp plain">ostream&
     storeOn( ostream &, Screen & );</code>
     
    <code class="cpp keyword bold">extern</code><code class="cpp plain">BitMap&
     storeOn( BitMap &, Screen & );</code>
     
    <code class="cpp comments">//
     ...</code>
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">Screen</code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">friend</code><code class="cpp plain">ostream&
     storeOn( ostream &, Screen & );</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">friend</code><code class="cpp plain">BitMap&
     storeOn( BitMap &, Screen & );</code>
     
    <code class="cpp spaces">    </code><code class="cpp comments">//
     ...</code>
     
    <code class="cpp plain">};</code>
     
    </td>
    </tr>
    </tbody>
    </table>
     
     
    如果一个函数操纵两个不同类类型的对象而且该函数需要访问这两个类的非公有成员,则这个函数可以被声明为这两个类的友元,或者作为一个类的成员函数并声明为另一个类的友元让我们来看一看怎样做:
     
     
    <h3 class="headline-2">
    被声明两个类的友元声明</h3>
    如果我们决定一个函数必须被声明为两个类的友元则友元声明如下
     
     
    <table border="0" cellpadding="0" cellspacing="0">
    <tbody>
    <tr>
    <td class="gutter">
     
    1
     
    2
     
    3
     
    4
     
    5
     
    6
     
    7
     
    8
     
    9
     
    10
     
    11
    </td>
    <td class="code">
     
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">Window;
    </code><code class="cpp comments">//
     只声明</code>
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">Screen</code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">friend</code><code class="cpp color1 bold">bool</code>
    <code class="cpp plain">
    is_equal( Screen &, Window & );</code>
     
    <code class="cpp spaces">    </code><code class="cpp comments">//
     ...</code>
     
    <code class="cpp plain">};</code>
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">Window
    </code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">friend</code><code class="cpp color1 bold">bool</code>
    <code class="cpp plain">
    is_equal( Screen &, Window & );</code>
     
    <code class="cpp spaces">    </code><code class="cpp comments">//
     ...</code>
     
    <code class="cpp plain">};</code>
     
    </td>
    </tr>
    </tbody>
    </table>
     
     
     
    <h3 class="headline-2">
    作为一个类的函数又是另一个类的友元</h3>
     
    如果我们决定该函数必须作为一个类的成员函数并又是另一个类的友元,则成员函数声明和友元声明如下:
     
     
     
    <table border="0" cellpadding="0" cellspacing="0">
    <tbody>
    <tr>
    <td class="code">
     
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">Window;</code>
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">Screen</code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp keyword bold">public</code><code class="cpp plain">:</code>
     
    <code class="cpp spaces">    </code><code class="cpp comments">//
     copy 是类 Screen 的成员</code>
     
    <code class="cpp spaces">    </code><code class="cpp plain">Screen&
     copy( Window & );</code>
     
    <code class="cpp spaces">    </code><code class="cpp comments">//
     ...</code>
     
    <code class="cpp plain">};</code>
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">Window</code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp comments">//
     copy 是类 Window 的一个友元</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">friend</code><code class="cpp plain">Screen&
     Screen::copy( Window & );</code>
     
    <code class="cpp spaces">    </code><code class="cpp comments">//
     ...</code>
     
    <code class="cpp plain">};</code>
     
    </td>
    </tr>
    </tbody>
    </table>
     
     
     
    只有当一个类的定义已经被看到时它的成员函数才能被声明为另一个类的友元。这并不总是能够做到的。
     
    例如如果Screen 类必须把Window 类的成员函数声明为友元,而Window类必须把Screen 类的成员函数声明为友元。该怎么办呢?在这种情况下可以把整个Window类声明为Screen 类的友元。
     
    例如:
     
     
    <table border="0" cellpadding="0" cellspacing="0">
    <tbody>
    <tr>
    <td class="gutter">
     
    1
     
    2
     
    3
     
    4
     
    5
     
    6
    </td>
    <td class="code">
     
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">Window;</code>
     
    <code class="cpp keyword bold">class</code><code class="cpp plain">Screen</code>
     
    <code class="cpp plain">{</code>
     
    <code class="cpp spaces">    </code><code class="cpp keyword bold">friend</code><code class="cpp keyword bold">class</code>
    <code class="cpp plain">
    Window;</code>
     
    <code class="cpp spaces">    </code><code class="cpp comments">//
     ...</code>
     
    <code class="cpp plain">};</code>
     
    </td>
    </tr>
    </tbody>
    </table>
     
     
     
    Screen 类的非公有成员现在可以被Window 的每个成员函数访问。
    <br>
    <p></p>
    <p class="tit">
    </p>                        </x<<","<<y<<")"<<endl;></cmath></iostream>
  • 相关阅读:
    makefile编写---单个子目录编译自动变量模板ok
    任务22:课程介绍 & 任务23:Http请求的处理过程
    任务20:DI初始化的源码解读 & 任务21:依赖注入的使用
    任务19:单元测试
    任务18:控制反转
    任务17:从UML角度来理解依赖
    任务16:介绍-
    任务15:配置框架设计浅析
    任务14:配置的热更新
    任务13:在Core Mvc中使用Options
  • 原文地址:https://www.cnblogs.com/shsgl/p/5147155.html
Copyright © 2011-2022 走看看