??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品丝袜久久久久久不卡,99久久精品久久久久久清纯,99久久国产亚洲高清观看2024http://www.shnenglu.com/ivy-jie/category/10520.htmlprogress ...zh-cnSun, 28 Jun 2009 07:55:02 GMTSun, 28 Jun 2009 07:55:02 GMT60有意思的矩阵输出?/title><link>http://www.shnenglu.com/ivy-jie/articles/88687.html</link><dc:creator>ivy-jie</dc:creator><author>ivy-jie</author><pubDate>Sun, 28 Jun 2009 04:04:00 GMT</pubDate><guid>http://www.shnenglu.com/ivy-jie/articles/88687.html</guid><wfw:comment>http://www.shnenglu.com/ivy-jie/comments/88687.html</wfw:comment><comments>http://www.shnenglu.com/ivy-jie/articles/88687.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivy-jie/comments/commentRss/88687.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivy-jie/services/trackbacks/88687.html</trackback:ping><description><![CDATA[<p>题目要求:<br>用C~写E序q注?br>N*N矩阵输出<br>N=3时输?br>1 2 3<br>  8 9 4<br>  7 6 5<br>NQ?时输?br>   1  2  3   4 <br>   12 13 14  5<br>   11 16 15  6<br>   10  9  8  7</p> <p>~写当N时的输出<br><br>代码:<br>#include <stdio.h><br>#include <stdlib.h><br>#include <string.h></p> <p>enum {<br>        MASK_UP                = 1,<br>        MASK_DOWN        = 2,<br>        MASK_LEFT        = 4,<br>        MASK_RIGHT        = 8,<br>        <br>        TURN_NONE        = 0,<br>        TURN_UP                = 1,<br>        TURN_DOWN        = 2,<br>        TURN_LEFT        = 3,<br>        TURN_RIGHT        = 4,<br>};</p> <p>int directs[5][2] = {<br>        {0, 0},                // 0:TURN_NONE<br>        {-1, 0},        // 1:TURN_UP<br>        {1, 0},                // 2:TURN_DOWN<br>        {0, -1},        // 3:TURN_LEFT<br>        {0, 1},                // 4:TURN_RIGHT<br>};</p> <p>int rules[16] = {<br>        TURN_NONE,        // 0:none<br>        TURN_UP,        // 1:up<br>        TURN_DOWN,        // 2:down<br>        TURN_NONE,        // 3:invalid<br>        TURN_LEFT,        // 4:left<br>        TURN_LEFT,        // 5:left and up<br>        TURN_DOWN,        // 6:left and down<br>        TURN_NONE,        // 7:invalid<br>        TURN_RIGHT,        // 8:right<br>        TURN_UP,        // 9:right and up<br>        TURN_RIGHT,        // 10:right and down<br>        TURN_NONE,        // 11-15:invalid<br>};<br>int next_pos(int *matrix, int n, int i, int j, int *nexti, int *nextj)<br>{<br>        if (i == -1 || j == -1)<br>        {<br>                *nexti = 0;<br>                *nextj = 0;<br>                return 1;<br>        }<br>        int mask = 0;<br>        if (i - 1 >= 0 && matrix[(i - 1) * n + j] == 0)                // up ok<br>                mask |= MASK_UP;<br>        if (i + 1 <= n - 1 && matrix[(i + 1) * n + j] == 0)        // down ok<br>                mask |= MASK_DOWN;<br>        if (j - 1 >= 0 && matrix[i * n + (j - 1)] == 0)                // left ok<br>                mask |= MASK_LEFT;<br>        if (j + 1 <= n - 1 && matrix[i * n + (j + 1)] == 0)        // right ok<br>                mask |= MASK_RIGHT;<br>        <br>        int rule = rules[mask];<br>        int *direct = directs[rule];<br>        if (direct[0] == 0 && direct[1] == 0)<br>                return 0;<br>        *nexti = i + direct[0];<br>        *nextj = j + direct[1];<br>        return 1;<br>}</p> <p>int main(int argc, char *argv[])<br>{<br>        if (argc != 2)<br>                return -1;<br>        int n = atoi(argv[1]);<br>        if (n <= 0)<br>                return -1;<br>        <br>        int *matrix = (int*)malloc(n * n * sizeof(int));<br>        memset(matrix, 0, n * n * sizeof(int));</p> <p>        int i = -1;<br>        int j = -1;<br>        int value = 1;<br>        while (next_pos(matrix, n, i, j, &i, &j) != 0)<br>        {<br>                matrix[i * n + j] = value++;<br>        }</p> <p>        for (i = 0; i < n; i++)<br>        {<br>                for (j = 0; j < n; j++)<br>                {<br>                        printf("%d", matrix[i * n + j]);<br>                        if (j != n - 1)<br>                                printf("\t");<br>                }<br>                printf("\n");<br>        }<br>        <br>        free(matrix);<br>        return 0;<br>}</p> <img src ="http://www.shnenglu.com/ivy-jie/aggbug/88687.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivy-jie/" target="_blank">ivy-jie</a> 2009-06-28 12:04 <a href="http://www.shnenglu.com/ivy-jie/articles/88687.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>虚承与虚基cȝ本质http://www.shnenglu.com/ivy-jie/articles/87104.htmlivy-jieivy-jieMon, 08 Jun 2009 14:34:00 GMThttp://www.shnenglu.com/ivy-jie/articles/87104.htmlhttp://www.shnenglu.com/ivy-jie/comments/87104.htmlhttp://www.shnenglu.com/ivy-jie/articles/87104.html#Feedback0http://www.shnenglu.com/ivy-jie/comments/commentRss/87104.htmlhttp://www.shnenglu.com/ivy-jie/services/trackbacks/87104.html虚承与虚基cȝ本质
    虚承和虚基cȝ定义是非常的单的Q同时也是非常容易判断一个承是否是虚?br>的,虽然q两个概늚定义是非常的单明的Q但是在C++语言中虚l承作ؓ(f)一个比较生
?ni)但是又是l对必要的组成部份而存在着Qƈ且其行ؓ(f)和模型均表现出和一般的l承体系
之间的巨大的差异Q包括访问性能上的差异Q,现在我们来d的从语言、模型、性能?br>应用{多个方面对虚承和虚基c进行研I?br>    首先q是先给l承和虚基类的定义?br>    虚承:(x)在承定义中包含了virtual关键字的l承关系Q?br>    虚基c:(x)在虚l承体系中的通过virtuall承而来的基c,需要注意的是:(x)
            struct CSubClass : public virtual CBase {}; 其中CBaseUC为CSubClass
            的虚基类Q而不是说CBase是个虚基类Q因为CBaseq可以不不是虚承体p?br>            中的基类?br>    有了上面的定义后Q就可以开始虚l承和虚基类的本质研I了Q下面按照语法、语义?br>模型、性能和应用五个方面进行全面的描述?br>
    1. 语法
       语法有语a的本w的定义所军_QM上来说非常的单,如下Q?br>           struct CSubClass : public virtual CBaseClass {};
       其中可以采用public、protected、private三种不同的承关键字q行修饰Q只?br>       保包含virtual可以了Q这样一来就形成了虚l承体系Q同时CBaseClass成?br>       了CSubClass的虚基类了?br>       其实q没有那么的单,如果出现虚承体pȝq一步承会(x)出现什么样的状况呢Q?br>       如下所C:(x)
            /*
             * 带有数据成员的基c?br>             */
            struct CBaseClass1
            {
                CBaseClass1( size_t i ) : m_val( i ) {}
            
                size_t m_val;
            };
            /*
             * 虚拟l承体系
             */
            struct CSubClassV1 : public virtual CBaseClass1
            {
                CSubClassV1( size_t i ) : CBaseClass1( i ) {}
            };           
            struct CSubClassV2 : public virtual CBaseClass1
            {
                CSubClassV2( size_t i ) : CBaseClass1( i ) {}
            };           
            struct CDiamondClass1 : public CSubClassV1, public CSubClassV2
            {
                CDiamondClass1( size_t i ) : CBaseClass1( i ), CSubClassV1( i ), CSubClassV2( i ) {}
            };           
            struct CDiamondSubClass1 : public CDiamondClass1
            {
                CDiamondSubClass1( size_t i ) : CBaseClass1( i ), CDiamondClass1( i ) {}
            };
       注意上面代码中的CDiamondClass1和CDiamondSubClass1两个cȝ构造函数初始化?br>       表中的内宏V可以发现其中均包含了虚基类CBaseClass1的初始化工作Q如果没有这
       个初始化语句׃(x)D~译旉误,Z么会(x)q样呢?一般情况下不是只要?br>       CSubClassV1和CSubClassV2中包含初始化可以了么?要解释该问题必须要明白虚
       l承的语义特征,所以参看下面语义部分的解释?br>      
    2. 语义
          在C++中虚函数必须要通过一U间接的q行Ӟ而不是编译时Q机制才能够Ȁz(
      调用Q的函数Q而虚l承也是必须在运行时才能够进行定位访问的一U体制。存在,
      但间接。其中关键就在于存在、间接和׃nq三U特征?br>       对于虚函数而言Q这三个特征是很好理解的Q间接性表明了他必dq行时根据实?br>       的对象来完成函数dQ共享性表象在基类?x)共享被子类重蝲后的虚函敎ͼ其实指?br>       相同的函数入口?br>       对于虚承而言Q这三个特征如何理解呢?存在卌Cl承体系和虚基类实存在Q?br>       间接性表明了在访问虚基类的成员时同样也必通过某种间接机制来完成(下面模型
       中会(x)讲到Q,׃n性表象在虚基cM(x)在虚l承体系中被׃nQ而不?x)出现多份拷贝?br>       那现在可以解释语法小节中留下来的那个问题了,“Z么一旦出C虚基c,必
       d每一个承类中都必须包含虚基cȝ初始化语?#8221;。由上面的分析可以知道,
       虚基cL被共享的Q也是在承体pM无论被承多次Q对象内存模型中均只?br>       出现一个虚基类的子对象Q这和多l承是完全不同的Q,q样一来既然是׃n的那?br>       每一个子c都不会(x)独占Q但是总还是必要有一个类来完成基cȝ初始化过E(因ؓ(f)
       所有的对象都必被初始化,哪怕是默认的)(j)Q同时还不能够重复进行初始化Q那?br>       底谁应该负责完成初始化呢QC++标准中(也是很自然的Q选择在每一ơ承子cM
       都必M写初始化语句Q因为每一ơ承子cd能都?x)用来定义对象?j)Q而在最下层
       l承子类中实际执行初始化q程。所以上面在每一个承类中都要书写初始化语句Q?br>       但是在创建对象时Q而仅仅会(x)在创建对象用的类构造函C实际的执行初始化语句Q?br>       其他的初始化语句都会(x)被压制不调用?br>      
    3. 模型
       Z实现上面所说的三种语义含义Q在考虑对象的实现模型(也就是内存模型)(j)时就
       很自然了。在C++中对象实际上是一个连l的地址I间的语义代表,我们来分析虚
       l承下的内存模型?br>       3.1. 存在
           也就是说在对象内存中必须要包含虚基类的完整子对象Q以便能够完成通过地址
           完成对象的标识。那么至于虚基类的子对象?x)存攑֜对象的那个位|(头、中间?br>           NQ则由各个编译器选择Q没有差别。(在VC8中无基类被声明在什么位|,
           虚基cȝ子对象都?x)被攄在对象内存的NQ?br>       3.2. 间接
           间接性表明了在直接虚基承子类中一定包含了某种指针Q偏UL表格Q来完成?br>           q子c访问虚基类子对象(或成员)(j)的间接手D(因ؓ(f)虚基cd对象是共享的Q?br>           没有定关系Q,至于采用何种手段q译器选择。(在VC8中在子类中放|了
           一个虚基类指针vbcQ该指针指向虚函数表中的一个slotQ该slot中存攑ֈ虚基
           cd对象的偏U量的负|实际上就是个以补码表C的intcd的|在计虚
           基类子对象首地址Ӟ需要将该偏U量取绝对值相加,q个主要是ؓ(f)了和虚表
           中只能存放虚函数地址q一要求相区别,因ؓ(f)地址是原码表C的无符号intcd
           的|(j)
       3.3. ׃n
           ׃n表明了在对象的内存空间中仅仅能够包含一份虚基类的子对象Qƈ且通过
           某种间接的机制来完成׃n的引用关pR在介绍完整个内容后?x)附上测试代码?br>           体现q些内容?br>    4. 性能
       ׃有了间接性和׃n性两个特征,所以决定了虚承体pM的对象在讉K时必?br>       ?x)在旉和空间上与一般情冉|较大不同?br>       4.1. 旉
           在通过l承cd象访问虚基类对象中的成员Q包括数据成员和函数成员Q时Q都
           必须通过某种间接引用来完成,q样?x)增加引用寻址旉Q就和虚函数一P(j)Q?br>           其实是调整this指针以指向虚基类对象Q只不过q个调整是运行时间接完成的?br>           Q在VC8中通过打开汇编输出Q可以查?.cod文g中的内容Q在讉K虚基cd?br>           成员时会(x)形成三条mov间接d语句Q而在讉K一般承类对象时仅仅只有一条mov
           帔R直接d语句Q?br>       4.2. I间
           ׃׃n所以不同在对象内存中保存多份虚基类子对象的拯Q这栯之多l承
           节省I间?br>    5. 应用
       谈了那么多语aҎ(gu)和内容Q那么在什么情况下需要用虚l承Q而一般应该如何
       用呢Q?br>       q个问题其实很难有答案,一般情况下如果你确性出现多l承没有必要Q必要׃n
       基类子对象的时候可以考虑采用虚承关p(C++标准ios体系是q样的)(j)。由于每
       一个承类都必d含初始化语句而又仅仅只在最底层子类中调用,q样可能׃(x)?br>       得某些上层子cd到的虚基cd对象的状态不是自己所期望的(因ؓ(f)自己的初始化?br>       句被压制了)(j)Q所?span style="COLOR: red">一般徏议不要在虚基cM包含M数据成员Q不要有状态)(j)Q只
       可以作ؓ(f)接口cL提供?br>               假定通过多个z路径l承名ؓ(f)X的成员,有下面三U可能性:(x)

            1Q如果在每个路径中X表示同一虚基cL员,则没有二义性,因ؓ(f)׃n该成员的单个实例Q?br>            2Q如果在某个路径中X是虚基类的成员,而在另一路径中X是后代派生类的成员,也没有二义性——特定派生类实例的优先高于׃n虚基cd例?nbsp;
            3Q如果沿每个l承路径X表示后代zcȝ不同成员Q则该成员的直接讉K是二义性的?br>




 
 


附录Q测试代?br>#include <ctime>
#include <iostream>

/*
 * 带有数据成员的基c?br> */
struct CBaseClass1
{
    CBaseClass1( size_t i ) : m_val( i ) {}

    size_t m_val;
};
/*
 * 虚拟l承体系
 */
struct CSubClassV1 : public virtual CBaseClass1
{
    CSubClassV1( size_t i ) : CBaseClass1( i ) {}
};

struct CSubClassV2 : public virtual CBaseClass1
{
    CSubClassV2( size_t i ) : CBaseClass1( i ) {}
};

struct CDiamondClass1 : public CSubClassV1, public CSubClassV2
{
    CDiamondClass1( size_t i ) : CBaseClass1( i ), CSubClassV1( i ), CSubClassV2( i ) {}
};

struct CDiamondSubClass1 : public CDiamondClass1
{
    CDiamondSubClass1( size_t i ) : CBaseClass1( i ), CDiamondClass1( i ) {}
};
/*
 * 正常l承体系
 */
struct CSubClassN1 : public CBaseClass1
{
    CSubClassN1( size_t i ) : CBaseClass1( i ) {}
};
struct CSubClassN2 : public CBaseClass1
{
    CSubClassN2( size_t i ) : CBaseClass1( i ) {}
};
struct CMultiClass1 : public CSubClassN1, public CSubClassN2
{
    CMultiClass1( size_t i ) : CSubClassN1( i ), CSubClassN2( i ) {}
};
struct CMultiSubClass1 : public CMultiClass1
{
    CMultiSubClass1( size_t i ) : CMultiClass1( i ) {}
};
/*
 * 不带有数据成员的接口基类
 */
struct CBaseClass2
{
    virtual void func() {};
    virtual ~CBaseClass2() {}
};
/*
 * 虚拟l承体系
 */
// struct CBaseClassX { CBaseClassX() {i1 = i2 = 0xFFFFFFFF;} size_t i1, i2;};
struct CSubClassV3 : public virtual CBaseClass2
{
};
struct CSubClassV4 : public virtual CBaseClass2
{
};
struct CDiamondClass2 : public CSubClassV3, public CSubClassV4
{
};
struct CDiamondSubClass2 : public CDiamondClass2
{
};

/*
 * 正常l承体系
 */
struct CSubClassN3 : public CBaseClass2
{
};
struct CSubClassN4 : public CBaseClass2
{
};
struct CMultiClass2 : public CSubClassN3, public CSubClassN4
{
};
struct CMultiSubClass2 : public CMultiClass2
{
};

/*
 * 内存布局用类声明.
 */
struct CLayoutBase1
{
    CLayoutBase1() : m_val1( 0 ), m_val2( 1 ) {}

    size_t m_val1, m_val2;
};
struct CLayoutBase2
{
    CLayoutBase2() : m_val1( 3 ) {}

    size_t m_val1;
};
struct CLayoutSubClass1 : public virtual CBaseClass1, public CLayoutBase1, public CLayoutBase2
{
    CLayoutSubClass1() : CBaseClass1( 2 ) {}
};


#define MAX_TEST_COUNT 1000 * 1000 * 16
#define TIME_ELAPSE() ( std::clock() - start * 1.0 ) / CLOCKS_PER_SEC

int main( int argc, char *argv[] )
{
    /*
     * cMpM的尺?
     */
    std::cout << "================================ sizeof ================================" << std::endl;
    std::cout << "    ----------------------------------------------------------------" << std::endl;
    std::cout << "sizeof( CBaseClass1 )       = " << sizeof( CBaseClass1 ) << std::endl;
    std::cout << std::endl;
    std::cout << "sizeof( CSubClassV1 )       = " << sizeof( CSubClassV1 ) << std::endl;
    std::cout << "sizeof( CSubClassV2 )       = " << sizeof( CSubClassV2 ) << std::endl;
    std::cout << "sizeof( CDiamondClass1 )    = " << sizeof( CDiamondClass1 ) << std::endl;
    std::cout << "sizeof( CDiamondSubClass1 ) = " << sizeof( CDiamondSubClass1 ) << std::endl;
    std::cout << std::endl;
    std::cout << "sizeof( CSubClassN1 )       = " << sizeof( CSubClassN1 ) << std::endl;
    std::cout << "sizeof( CSubClassN2 )       = " << sizeof( CSubClassN2 ) << std::endl;
    std::cout << "sizeof( CMultiClass1 )      = " << sizeof( CMultiClass1 ) << std::endl;
    std::cout << "sizeof( CMultiSubClass1 )   = " << sizeof( CMultiSubClass1 ) << std::endl;

    std::cout << "    ----------------------------------------------------------------" << std::endl;
    std::cout << "sizeof( CBaseClass2 )       = " << sizeof( CBaseClass2 ) << std::endl;
    std::cout << std::endl;
    std::cout << "sizeof( CSubClassV3 )       = " << sizeof( CSubClassV3 ) << std::endl;
    std::cout << "sizeof( CSubClassV4 )       = " << sizeof( CSubClassV4 ) << std::endl;
    std::cout << "sizeof( CDiamondClass2 )    = " << sizeof( CDiamondClass2 ) << std::endl;
    std::cout << "sizeof( CDiamondSubClass2 ) = " << sizeof( CDiamondSubClass2 ) << std::endl;
    std::cout << std::endl;
    std::cout << "sizeof( CSubClassN3 )       = " << sizeof( CSubClassN3 ) << std::endl;
    std::cout << "sizeof( CSubClassN4 )       = " << sizeof( CSubClassN4 ) << std::endl;
    std::cout << "sizeof( CMultiClass2 )      = " << sizeof( CMultiClass2 ) << std::endl;
    std::cout << "sizeof( CMultiSubClass2 )   = " << sizeof( CMultiSubClass2 ) << std::endl;
    /*
     * 对象内存布局
     */
    std::cout << "================================ layout ================================" << std::endl;
    std::cout << "    --------------------------------MI------------------------------" << std::endl;
    CLayoutSubClass1 *lsc = new CLayoutSubClass1;
    std::cout << "sizeof( CLayoutSubClass1 )   = " << sizeof( CLayoutSubClass1 ) << std::endl;
    std::cout << "CLayoutBase1 offset of CLayoutSubClass1 is " << (char*)(CLayoutBase1 *)lsc - (char*)lsc << std::endl;
    std::cout << "CBaseClass1  offset of CLayoutSubClass1 is " << (char*)(CBaseClass1  *)lsc - (char*)lsc << std::endl;
    std::cout << "CLayoutBase2 offset of CLayoutSubClass1 is " << (char*)(CLayoutBase2 *)lsc - (char*)lsc << std::endl;

    int *ptr = (int*)lsc;
    std::cout << "vbc in CLayoutSubClass1 is " << *(int*)ptr[3] << std::endl;

    delete lsc;

    std::cout << "    --------------------------------SI------------------------------" << std::endl;
    CSubClassV1 *scv1 = new CSubClassV1( 1 );
    std::cout << "sizeof( CSubClassV1 )   = " << sizeof( CSubClassV1 ) << std::endl;
    std::cout << "CBaseClass1 offset of CSubClassV1 is " << (char*)(CBaseClass1 *)scv1 - (char*)scv1 << std::endl;

    ptr = (int*)scv1;
    std::cout << "vbc in CSubClassV1 is " << *(int*)ptr[0] << std::endl;

    delete scv1;

    /*
     * 性能试
     */
    std::cout << "================================ Performance ================================" << std::endl;
    double times[4];
    size_t idx = 0;

    CSubClassV1 *ptr1 = new CDiamondClass1( 1 );
    std::clock_t start = std::clock();
    {
        for ( size_t i = 0; i < MAX_TEST_COUNT; ++i )
            ptr1->m_val = i;
    }
    times[idx++] = TIME_ELAPSE();
    delete static_cast<CDiamondClass1*>( ptr1 );

    CSubClassN1 *ptr2 = new CMultiClass1( 0 );
    start = std::clock();
    {
        for ( size_t i = 0; i < MAX_TEST_COUNT; ++i )
            ptr2->m_val = i;
    }
    times[idx++] = TIME_ELAPSE();
    delete static_cast<CMultiClass1*>( ptr2 );

    std::cout << "CSubClassV1::ptr1->m_val " << times[0] << " s" << std::endl;
    std::cout << "CSubClassN1::ptr2->m_val " << times[1] << " s" << std::endl;

    return 0;
}

试环境Q?br>    软g环境QVisual Studio2005 Pro + SP1, boost1.34.0
    g环境QPentiumD 3.0GHz, 4G RAM
试数据Q?br>================================ sizeof ================================
    ----------------------------------------------------------------
sizeof( CBaseClass1 )       = 4

sizeof( CSubClassV1 )       = 8
sizeof( CSubClassV2 )       = 8
sizeof( CDiamondClass1 )    = 12
sizeof( CDiamondSubClass1 ) = 12

sizeof( CSubClassN1 )       = 4
sizeof( CSubClassN2 )       = 4
sizeof( CMultiClass1 )      = 8
sizeof( CMultiSubClass1 )   = 8
    ----------------------------------------------------------------
sizeof( CBaseClass2 )       = 4

sizeof( CSubClassV3 )       = 8
sizeof( CSubClassV4 )       = 8
sizeof( CDiamondClass2 )    = 12
sizeof( CDiamondSubClass2 ) = 12

sizeof( CSubClassN3 )       = 4
sizeof( CSubClassN4 )       = 4
sizeof( CMultiClass2 )      = 8
sizeof( CMultiSubClass2 )   = 8
================================ layout ================================
    --------------------------------MI------------------------------
sizeof( CLayoutSubClass1 )   = 20
CLayoutBase1 offset of CLayoutSubClass1 is 0
CBaseClass1  offset of CLayoutSubClass1 is 16
CLayoutBase2 offset of CLayoutSubClass1 is 8
vbc in CLayoutSubClass1 is -12
    --------------------------------SI------------------------------
sizeof( CSubClassV1 )   = 8
CBaseClass1 offset of CSubClassV1 is 4
vbc in CSubClassV1 is 0
================================ Performance ================================
CSubClassV1::ptr1->m_val 0.062 s
CSubClassN1::ptr2->m_val 0.016 s

l果分析Q?br>    1. ׃虚承引入的间接性指针所以导致了虚承类的尺怼(x)增加4个字节;
    2. 由Layout输出可以看出Q虚基类子对象被攑֜了对象的NQ偏UMؓ(f)16Q,q且vbc
       指针必须紧紧的接在虚基类子对象的前面Q所以vbc指针所指向的内容ؓ(f)“偏移 - 4”Q?br>    3. ׃VC8偏UL在了虚函数表中,所以ؓ(f)了区分函数地址和偏U,所以偏UL用补
       码int表示的负|
    4. 间接性可以通过性能来看出,在虚l承体系同通过指针讉K成员时的旉一般是一?br>       c访问情况下?倍左叻IW合汇编语言输出文g中的汇编语句的安排?br>


ivy-jie 2009-06-08 22:34 发表评论
]]>
一道多l承和虚l承的面试题http://www.shnenglu.com/ivy-jie/articles/87102.htmlivy-jieivy-jieMon, 08 Jun 2009 14:30:00 GMThttp://www.shnenglu.com/ivy-jie/articles/87102.htmlhttp://www.shnenglu.com/ivy-jie/comments/87102.htmlhttp://www.shnenglu.com/ivy-jie/articles/87102.html#Feedback0http://www.shnenglu.com/ivy-jie/comments/commentRss/87102.htmlhttp://www.shnenglu.com/ivy-jie/services/trackbacks/87102.html
class A{
public A { std::cout<<A<<}
}

class B: public A{
... // print B
}

class C: public A, pulic B {
... // print C
}

int main(){
C obj;
}
输出: AABC。承关pL三角形:(x)A->B->C加A->C?br>
问题是:(x)q三条边如果考虑虚承,每条Ҏ(gu)两种可能Q共八种。那么其他七U组合的
输出是什么?
~译? VC6.0
#include "stdafx.h"
#include "iostream"
using namespace std;
class AA {
public:
 AA(){ std::cout<<"AA"<<endl;}
};
class BB: public virtual AA
{
public:
 BB(){ std::cout<<"BB"<<endl;}
};

class CC: public virtual AA,  public (virtual) BB //括号的virtual可有可无
{
public:
 CC(){ std::cout<<"CC"<<endl;}
};

int main(int argc, char* argv[])
{
 CC obj;

 return 0;
}
输出: AA
          BB
          CC
其它情况~译?x)出?br>主要考察多承的虚基cd内存中只有一份copy,如果不用虚承的话,Ҏ(gu)造成二义性,~译不过:)



ivy-jie 2009-06-08 22:30 发表评论
]]>
面向q程的静态成?/title><link>http://www.shnenglu.com/ivy-jie/articles/85576.html</link><dc:creator>ivy-jie</dc:creator><author>ivy-jie</author><pubDate>Sun, 24 May 2009 02:47:00 GMT</pubDate><guid>http://www.shnenglu.com/ivy-jie/articles/85576.html</guid><wfw:comment>http://www.shnenglu.com/ivy-jie/comments/85576.html</wfw:comment><comments>http://www.shnenglu.com/ivy-jie/articles/85576.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivy-jie/comments/commentRss/85576.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivy-jie/services/trackbacks/85576.html</trackback:ping><description><![CDATA[1、静态全局变量 <br><br>在全局变量前,加上关键字staticQ该变量p定义成ؓ(f)一个静态全局变量。我们先举一个静态全局变量的例子,如下Q?<br>//Example 1#include <iostream.h>void fn();static int n; //定义静态全局变量void main(){ n=20; cout<<n<<endl; fn();}void fn(){ n++; cout<<n<<endl;} <br><br>静态全局变量有以下特点:(x) <br>该变量在<span style="COLOR: red"><u><strong>全局数据?/strong></u></span>分配内存Q?<br>未经初始化的静态全局变量?x)被E序自动初始化ؓ(f)0Q自动变量的值是随机的,除非它被昑ּ初始化)(j)Q?<br><span style="COLOR: red"><u><strong>静态全局变量在声明它的整个文仉是可见的Q而在文g之外是不可见的;</strong></u></span> <br>静态变量都在全局数据区分配内存,包括后面要提到的静态局部变量。对于一个完整的E序Q在内存中的<br><br><span style="COLOR: red"><u><strong>分布情况如下图:(x) <br>代码?<br>全局数据?<br>堆区 <br>栈区</strong></u></span> <br><br>一般程序的由new产生的动态数据存攑֜堆区Q函数内部的自动变量存放在栈区。自动变量一般会(x)随着函数的退释攄_(d)静态数据(即是函数内部的?态局部变量)(j)也存攑֜全局数据区。全局数据区的数据q不?x)因为函数的退释攄间。细心的读者可能会(x)发现QExample 1中的代码中将 <br><br><strong><span style="COLOR: red"><u>static int n; //定义静态全局变量</u></span></strong> <br>改ؓ(f) <br><strong style="COLOR: red"><u>int n; //定义全局变量</u></strong> <br>E序照样正常q行?<br>的确Q?strong><u style="COLOR: red">定义全局变量可以实现变量在文g中的׃nQ但定义静态全局变量q有以下好处Q?<br>静态全局变量不能被其它文件所用; <br>其它文g中可以定义相同名字的变量Q不?x)发生冲H;</u></strong> <br>(zhn)可以将上述CZ代码改ؓ(f)如下Q?<br><br><span style="COLOR: red"><u><strong>//Example 2//File1#include <iostream.h>void fn();static int n; //定义静态全局变量void main(){ n=20; cout<<n<<endl; fn();}//File2#include <iostream.h><span style="COLOR: #000000">extern int n;</span>void fn(){ n++; cout<<n<<endl;} <br>~译q运行Example 2Q?zhn)׃?x)发现上述代码可以分别通过~译Q但q行时出现错误?试着?<br>static int n; //定义静态全局变量 <br>改ؓ(f) <br>int n; //定义全局变量 <br>再次~译q行E序Q细心体?x)全局变量和静态全局变量的区别?<br></strong></u></span>2、静态局部变?<br><br>在局部变量前Q加上关键字staticQ该变量p定义成ؓ(f)一个静态局部变量?<br><br>我们先D一个静态局部变量的例子Q如下:(x) <br><br>//Example 3#include <iostream.h>void fn();void main(){ fn(); fn(); fn();}void fn(){ static n=10; cout<<n<<endl; n++;} <br>通常Q在函数体内定义了一个变量,每当E序q行到该语句旉?x)给该局部变量分配栈内存。但随着E序退出函CQ系l就?x)收回栈内存Q局部变量也相应失效?<br>但有时候我们需要在两次调用之间对变量的D行保存。通常的想法是定义一个全局变量来实现。但q样一来,变量已经不再属于函数本n了,不再仅受函数的控Ӟl程序的l护带来不便?<br>静态局部变量正好可以解册个问题。静态局部变量保存在全局数据区,而不是保存在栈中Q每ơ的g持到下一ơ调用,直到下次赋新倹{?<br>静态局部变量有以下特点Q?<br><br>该变量在全局数据区分配内存; <br>静态局部变量在E序执行到该对象的声明处时被首次初始化,即以后的函数调用不再q行初始化; <br>静态局部变量一般在声明处初始化Q如果没有显式初始化Q会(x)被程序自动初始化?Q?<br><span style="COLOR: #ff0000"><u><strong>它始l驻留在全局数据区,直到E序q行l束。但?span style="COLOR: #000000">作用域ؓ(f)局部作用域</span>Q当定义它的函数或语句块l束Ӟ其作用域随之l束Q?<br></strong></u></span>3、静态函?<br><br>在函数的q回cd前加上static关键?函数卌定义为静态函数。静态函C普通函C同,它只能在声明它的文g当中可见Q不能被其它文g使用?<br><br>静态函数的例子Q?<br><br>//Example 4#include <iostream.h>static void fn();//声明静态函数void main(){ fn();}void fn()//定义静态函数{ int n=10; cout<<n<<endl;} <br>定义静态函数的好处Q?<br><span style="COLOR: #ff0000"><u><strong>静态函C能被其它文g所用; <br>其它文g中可以定义相同名字的函数Q不?x)发生冲H;</strong></u></span> <img src ="http://www.shnenglu.com/ivy-jie/aggbug/85576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivy-jie/" target="_blank">ivy-jie</a> 2009-05-24 10:47 <a href="http://www.shnenglu.com/ivy-jie/articles/85576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>面向对象的静态成?/title><link>http://www.shnenglu.com/ivy-jie/articles/85575.html</link><dc:creator>ivy-jie</dc:creator><author>ivy-jie</author><pubDate>Sun, 24 May 2009 02:42:00 GMT</pubDate><guid>http://www.shnenglu.com/ivy-jie/articles/85575.html</guid><wfw:comment>http://www.shnenglu.com/ivy-jie/comments/85575.html</wfw:comment><comments>http://www.shnenglu.com/ivy-jie/articles/85575.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivy-jie/comments/commentRss/85575.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivy-jie/services/trackbacks/85575.html</trackback:ping><description><![CDATA[ 静态类成员包括<font color=#ff0000>静态数据成?/font>?font color=#ff0000>静态函数成?/font>两部分?nbsp;  <br>    <br>1<strong> 静态数据成员:(x)</strong>   <br>   <br>   <br>      cM中的数据成员的声明前加上<font color=#3366ff>static</font>关键字,该数据成员就成ؓ(f)了该cȝ<font color=#ff0000>静态数据成?/font>。和其他数据成员一P<font color=#ff0000>静态数据成?/font>也遵?font color=#3366ff>public/protected/private</font>讉K规则。同Ӟ<font color=#ff0000>静态数据成?/font>q具有以下特点:(x)   <br>    <br>        1.静态数据成员的定义?  <br>           <span style="COLOR: red"> 静态数据成员实际上是类域中的全局变量。所以,<font style="COLOR: red" color=#000000>静态成员不能在cd义里边初始化Q只能在class body外初始化?/font></span>    举例如下Q?  <br>    <br>        xxx.h文g   <br>        class   base{   <br>            private:   <br>            static   const   int   _i;//声明Q标准c++支持有序cd在类体中初始?但vc6不支持?  <br>        };     <br>    <br>        xxx.cpp文g   <br>        const   int   base::_i=10;//<span style="COLOR: red"><u><strong>定义(初始?时不受private和protected讉K限制.</strong></u></span>   <br>    <em>   <br></em>    <br>        2.<span style="COLOR: red"><font color=#ff0000>静态数据成?/font>?font color=#ff0000>c?/font>的所有对象所׃nQ包括该cL生类的对象?/span>x生类对象与基cd象共享基cȝ静态数据成员?nbsp;<br>  <br><span style="COLOR: red"><strong><u>        3 初始?或定?Q访问方?br></u></strong></span><br>         静态数据成员初始化的格式ؓ(f)Q?<br>        Q数据类型>Q类名>::Q静态数据成员名Q?Q| <br>       cȝ静态数据成员有两种讉K形式Q?<br>        Q类对象名><u><strong style="COLOR: red">.</strong></u>Q静态数据成员名Q??Q类cd名><span style="COLOR: red"><u><strong>::</strong></u></span>Q静态数据成员名Q?<br>       如果静态数据成员的讉K权限允许的话Q?span style="COLOR: red"><u><strong>即public的成?/strong></u></span>Q,可在E序中,按上q格式来引用静态数据成?nbsp;;<br><br>  <br>       3.<font style="COLOR: #000000" color=#ff0000>静态数据成?/font>可以成ؓ(f)成员函数的可选参敎ͼ而普通数据成员则不可以。D例如下:(x)   <br>      class   base{   <br>          public   :   <br>          static   int   _staticVar;   <br>          int   _var;   <br>          void   foo1(int   i=_staticVar);//<font color=#339966>正确,_staticVar为静态数据成?/font>   <br>          void   foo2(int   i=_var);//<font color=#339966>错误,_var为普通数据成?/font>   <br>      };           <br>        <br>      4.?font style="COLOR: #000000" color=#ff0000>静态数据成?/font>的类型可以是所属类的类型,而普通数据成员则不可以。普通数据成员的只能声明?nbsp;所属类cd的指针或引用。D例如下:(x)   <br>        <br>      class   base{   <br>          public   :   <br>          static   base   _object1;//正确Q静态数据成?  <br>          base   _object2;//错误   <br>          base   *pObject;//正确Q指?  <br>          base   &mObject;//正确Q引?  <br>      };   <br>    <br>    5.★这个特性,我不知道是属于标准c++中的Ҏ(gu),q是vc6自己的特性?  <br>        静态数据成员的值在const成员函数中可以被合法的改变。D例如下:(x)   <br>    <br>      class   base{   <br>          public:   <br>          base(){_i=0;_val=0;}   <br>    <br>          mutable   int   _i;   <br>          static   int   _staticVal;     <br>          int   _val;   <br>          void   test()   const{//const   成员函数   <br>    <br>                _i++;//正确Qmutable数据成员   <br>                _staticVal++;//正确Qstatic数据成员   <br>                _val++;//错误   <br>    <br>          }   <br>      };   <br>      int   base::_staticVal=0;   <br>    <br><strong>2  静态成员函?/strong>   <br>     <br>      1.静态成员函数的地址可用普通函数指针储存,而普通成员函数地址需要用   cL员函数指针来储存。D例如下:(x)   <br>          class   base{   <br>              static   int   func1();   <br>              int   func2();   <br>          };   <br>    <br>          int   (*pf1)()=&base::func1;//普通的函数指针   <br>          int   (base::*pf2)()=&base::func2;//成员函数指针   <br>    <br>    2.<span style="COLOR: red">静态成员函C可以调用cȝ非静态成员?u><strong>因ؓ(f)静态成员函C含this指针</strong></u></span><u><strong>?/strong></u>   <br>     通常情况下,this 是缺省的。如函数fn()实际上是this->fn()。但是与普通函数相比,静态成员函数由于不是与M的对象相联系Q因此它不具有this?针。从q个意义上讲Q?span style="COLOR: red"><u><strong>它无法访问属于类对象的非静态数据成?/strong></u></span>Q?span style="COLOR: red"><u><strong>也无法访问非静态成员函?/strong></u></span>Q它<span style="COLOR: red"><u><strong>只能调用其余的静态成员函?/strong></u></span>?nbsp;<br>    <br>      3.静态成员函C可以同时声明?  virtual、const、volatile函数。D例如下:(x)   <br>        class   base{   <br>              virtual   static   void   func1();//错误   <br>              static   void   func2()   const;//错误   <br>              static   void   func3()   volatile;//错误   <br>                     };   <br><br>3   静态构造函?br>     静态构造函数自动被调用Q不能被昑ּ调用。虽然提供了许多U束条gQ但是静态构造函数执行的切旉和顺序是不确定的Q?br>一个类的静态构造函数在q个cȝM实例被创建前执行?br>一个类的静态构造函数在cȝM静态成员被引用前执行?br>一个类的静态构造函数在它的所有派生类的静态构造函数执行之后执行?br>一个类的静态构造函C不会(x)被执行一ơ以上?br> <img src ="http://www.shnenglu.com/ivy-jie/aggbug/85575.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivy-jie/" target="_blank">ivy-jie</a> 2009-05-24 10:42 <a href="http://www.shnenglu.com/ivy-jie/articles/85575.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>子类父类构造函数调用顺?/title><link>http://www.shnenglu.com/ivy-jie/articles/85481.html</link><dc:creator>ivy-jie</dc:creator><author>ivy-jie</author><pubDate>Fri, 22 May 2009 16:27:00 GMT</pubDate><guid>http://www.shnenglu.com/ivy-jie/articles/85481.html</guid><wfw:comment>http://www.shnenglu.com/ivy-jie/comments/85481.html</wfw:comment><comments>http://www.shnenglu.com/ivy-jie/articles/85481.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivy-jie/comments/commentRss/85481.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivy-jie/services/trackbacks/85481.html</trackback:ping><description><![CDATA[<p style="TEXT-INDENT: 2em">子类l承和调用父cȝ构造方?/p> <p style="TEXT-INDENT: 2em"> <table> <tbody> <tr> <td> <p> </p> <p style="TEXT-INDENT: 2em">1.如果子类没有定义构造方?则调用父cȝ无参数的构造方?.</p> <p style="COLOR: red; TEXT-INDENT: 2em">2.如果子类定义了构造方?不论是无参数q是带参?在创建子cȝ对象的时?首先<u><strong>执行父类无参数的构造方?/strong></u>,然后执行自己的构造方法?/p> <p style="TEXT-INDENT: 2em">3.如果子类调用父类带参数的构造方?可以通过super(参数)调用所需要的父类的构造方?切该语句做ؓ(f)<span style="COLOR: red">子类构造方法中的第一条语?/span>?/p> <p style="TEXT-INDENT: 2em">4.如果某个构造方法调用类中的其他的构造方?则可以用this(参数),切该语句攑֜构造方法的W一?</p> <p style="TEXT-INDENT: 2em">说白?原则是,先调用父亲的.(没有默认调,有了按有的?反正只要有一个就可以?)</p> <p style="TEXT-INDENT: 2em">package test;</p> <p style="TEXT-INDENT: 2em">class Father{</p> <p style="TEXT-INDENT: 2em">String s = "Run constructor method of Father";</p> <p style="TEXT-INDENT: 2em">public Father(){</p> <p style="TEXT-INDENT: 2em">   System.out.println(s);</p> <p style="TEXT-INDENT: 2em">}</p> <p style="TEXT-INDENT: 2em">public Father(String str){</p> <p style="TEXT-INDENT: 2em">   s= str;</p> <p style="TEXT-INDENT: 2em">   System.out.println(s);</p> <p style="TEXT-INDENT: 2em">}</p> <p style="TEXT-INDENT: 2em">}</p> <p style="TEXT-INDENT: 2em">class Son extends Father{</p> <p style="TEXT-INDENT: 2em">String s= "Run constructor method of son";</p> <p style="TEXT-INDENT: 2em">public Son(){</p> <p style="TEXT-INDENT: 2em">   //实际上在q里加上super()Q和没加是一个样?/p> <p style="TEXT-INDENT: 2em">   System.out.println(s);</p> <p style="TEXT-INDENT: 2em">}</p> <p style="TEXT-INDENT: 2em">public Son(String str){</p> <p style="TEXT-INDENT: 2em">   this();//q里调用this()表示调用本类的Son(),因ؓ(f)Son()中有了一个super()了,所以这里不能再加了?/p> <p style="TEXT-INDENT: 2em">   s = str;</p> <p style="TEXT-INDENT: 2em">   System.out.println(s);</p> <p style="TEXT-INDENT: 2em">}</p> <p style="TEXT-INDENT: 2em">public Son(String str1, String str2){</p> <p style="TEXT-INDENT: 2em">   super(str1+" "+str2);//因ؓ(f)q里已经调用了一个父cȝ带参数的super("---")了,所以不?x)再自动调用了无参数的了?/p> <p style="TEXT-INDENT: 2em">   s = str1;</p> <p style="TEXT-INDENT: 2em">   System.out.println(s);</p> <p style="TEXT-INDENT: 2em">}</p> <p style="TEXT-INDENT: 2em">}</p> <p style="TEXT-INDENT: 2em">public class MyClass9 {</p> <p style="TEXT-INDENT: 2em">public static void main(String[] args){</p> <p style="TEXT-INDENT: 2em">   Father obfather1 = new Father();</p> <p style="TEXT-INDENT: 2em">   Father obfather2 = new Father("Hello Father");</p> <p style="TEXT-INDENT: 2em">   Son obson1 = new Son();</p> <p style="TEXT-INDENT: 2em">   Son obson2 = new Son("hello son");</p> <p style="TEXT-INDENT: 2em">   Son obson3 = new Son("hello son","hello father");</p> <p style="TEXT-INDENT: 2em">  </p> <p style="TEXT-INDENT: 2em">}</p> <p style="TEXT-INDENT: 2em">}</p> <p style="TEXT-INDENT: 2em">===============</p> <p style="TEXT-INDENT: 2em">l果:</p> <p style="TEXT-INDENT: 2em">Run constructor method of Father</p> <p style="TEXT-INDENT: 2em">Hello Father</p> <p style="TEXT-INDENT: 2em">Run constructor method of Father</p> <p style="TEXT-INDENT: 2em">Run constructor method of son</p> <p style="TEXT-INDENT: 2em">Run constructor method of Father</p> <p style="TEXT-INDENT: 2em">Run constructor method of son</p> <p style="TEXT-INDENT: 2em">hello son</p> <p style="TEXT-INDENT: 2em">hello son hello father</p> <p style="TEXT-INDENT: 2em">hello son</p> </td> </tr> </tbody> </table> </p> <img src ="http://www.shnenglu.com/ivy-jie/aggbug/85481.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivy-jie/" target="_blank">ivy-jie</a> 2009-05-23 00:27 <a href="http://www.shnenglu.com/ivy-jie/articles/85481.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>输入函数scanf()详解http://www.shnenglu.com/ivy-jie/articles/85332.htmlivy-jieivy-jieFri, 22 May 2009 01:01:00 GMThttp://www.shnenglu.com/ivy-jie/articles/85332.htmlhttp://www.shnenglu.com/ivy-jie/comments/85332.htmlhttp://www.shnenglu.com/ivy-jie/articles/85332.html#Feedback0http://www.shnenglu.com/ivy-jie/comments/commentRss/85332.htmlhttp://www.shnenglu.com/ivy-jie/services/trackbacks/85332.html  如果你:(x)  
  char   c[20];  
  scanf("%s",c);  
  输入:this   is   a   c   program!   
 
  它接收到this后遇到空|认ؓ(f)对应%s的数据项已结束,后面的(包含I格Q不能输入? 
  你想输入带空格的字符Ԍ只有使用gets(c);  
  但遗憄是用gets()函数一ơ只能输入一个字W串?br> 2 ȝ
%d,遇到数字,'+','-'以外的字W结?可蟩q空?

%f,,%lf:遇到数字, '.', 'e','+','-'之外的字W结?可蟩q空?br>
%s,从第一个非I格字符L(fng)C一个空格结?

%c,遇到字符p?不管是空D是回车之cȝ.

  假如E序中出现这L(fng)代码,scanf("%d,%s,%c,%c").虽然E序是以 ', '作ؓ(f)分隔??s是不认这?', '?它只认空?所以会(x)出现变量不能正确赋值的情况,如果你将','L,但由?c却遇到空格又不会(x)跌,所以也不会(x)满需?通过上面的我们知?%c遇到I格是不?x)蟩q的,所以我采取下面q个方式来解??c的前面加一个空格来处理,q样可以解决上面的所有问题了,所以我们在使用%c?要在前面加上一个空?/span>,Lq种?fn)惯可以省去不少ȝ?ch),q且在?c之前最好还加上一?span style="COLOR: #ff0000">fflush(stdin);用来清除~存.
3 gets()
   功能:从stdin中d字符Ԍ直至接受到换行符或EOF时停止,q将d的结果存攑֜str指针所指向的字W数l中。换行符不作取串的内容,d的换行符被{换ؓ(f)null|q由此来l束字符丌Ӏ?br>   注意:本函数可以无限读取,不会(x)判断上限Q所以程序员应该保str的空间够大Q以便在执行L作时不发生溢出?br>   实例Q?include"stdio.h"
                  void main()
                   {
                            char str[15];
                            gets(str);
                            printf("%s/n",str);

                   }

 





ivy-jie 2009-05-22 09:01 发表评论
]]>
?qsort七种应用http://www.shnenglu.com/ivy-jie/articles/83327.htmlivy-jieivy-jieMon, 18 May 2009 15:52:00 GMThttp://www.shnenglu.com/ivy-jie/articles/83327.htmlhttp://www.shnenglu.com/ivy-jie/comments/83327.htmlhttp://www.shnenglu.com/ivy-jie/articles/83327.html#Feedback0http://www.shnenglu.com/ivy-jie/comments/commentRss/83327.htmlhttp://www.shnenglu.com/ivy-jie/services/trackbacks/83327.html
<本文中排序都是采用的从小到大排序>

一、对intcd数组排序

int num[100];

Sample:

int cmp ( const void *a , const void *b )
{
return *(int *)a - *(int *)b;
}

qsort(num,100,sizeof(num[0]),cmp);

二、对charcd数组排序Q同intcdQ?

char word[100];

Sample:

int cmp( const void *a , const void *b )
{
return *(char *)a - *(int *)b;
}

qsort(word,100,sizeof(word[0]),cmp);

三、对doublecd数组排序Q特别要注意Q?

double in[100];

int cmp( const void *a , const void *b )
{
return *(double *)a > *(double *)b ? 1 : -1;
}

qsort(in,100,sizeof(in[0]),cmp)Q?

四、对l构体一U排?

struct In
{
double data;
int other;
}s[100]

//按照data的g到大将l构体排?关于l构体内的排序关键数据data的类型可以很多种Q参考上面的例子?

int cmp( const void *a ,const void *b)
{
return (*(In *)a).data > (*(In *)b).data ? 1 : -1;
}

qsort(s,100,sizeof(s[0]),cmp);

五、对l构体二U排?

struct In
{
int x;
int y;
}s[100];

//按照x从小到大排序Q当x相等时按照y从大到小排序

int cmp( const void *a , const void *b )
{
struct In *c = (In *)a;
struct In *d = (In *)b;
if(c->x != d->x) return c->x - d->x;
else return d->y - c->y;
}

qsort(s,100,sizeof(s[0]),cmp);

六、对字符串进行排?

struct In
{
int data;
char str[100];
}s[100];

//按照l构体中字符串str的字兔R序排?

int cmp ( const void *a , const void *b )
{
return strcmp( (*(In *)a)->str , (*(In *)b)->str );
}

qsort(s,100,sizeof(s[0]),cmp);

七、计几何中求凸包的cmp

int cmp(const void *a,const void *b) //重点cmp函数Q把除了1点外的所有点Q旋转角度排?
{
struct point *c=(point *)a;
struct point *d=(point *)b;
if( calc(*c,*d,p[1]) < 0) return 1;
else if( !calc(*c,*d,p[1]) && dis(c->x,c->y,p[1].x,p[1].y) < dis(d->x,d->y,p[1].x,p[1].y)) //如果在一条直U上Q则把远的放在前?
return 1;
else return -1;
}

PS:

其中的qsort函数包含?lt;stdlib.h>的头文g里,strcmp包含?lt;string.h>的头文g?

ivy-jie 2009-05-18 23:52 发表评论
]]>
C++言1:l不在构造或析构期调用虚函数http://www.shnenglu.com/ivy-jie/articles/83251.htmlivy-jieivy-jieMon, 18 May 2009 09:26:00 GMThttp://www.shnenglu.com/ivy-jie/articles/83251.htmlhttp://www.shnenglu.com/ivy-jie/comments/83251.htmlhttp://www.shnenglu.com/ivy-jie/articles/83251.html#Feedback0http://www.shnenglu.com/ivy-jie/comments/commentRss/83251.htmlhttp://www.shnenglu.com/ivy-jie/services/trackbacks/83251.html
class Transaction { // base class for all
 public: // transactions
  Transaction();

  virtual void logTransaction() const = 0; // make type-dependent
  // log entry
  ...
};

Transaction::Transaction() // implementation of
{
 // base class ctor
 ...
 logTransaction(); // as final action, log this
} // transaction

class BuyTransaction: public Transaction {
 // derived class
 public:
  virtual void logTransaction() const; // how to log trans-
  // actions of this type
  ...
};

class SellTransaction: public Transaction {
// derived class
public:
 virtual void logTransaction() const; // how to log trans-
 // actions of this type
...
};

  考虑执行q行代码时会(x)发生什么:(x)

BuyTransaction b;

  很明?BuyTransaction 的构造函C(x)被调用,但是首先QTransaction 的构造函数必d被调用,zcd象中的基c部分先于派生类部分被构造。Transaction 的构造函数的最后一行调用虚函数 logTransactionQ但是结果会(x)让你大吃一惊,被调用的 logTransaction 版本是在 Transaction 中的那个Q而不?BuyTransaction 中的——即使被创徏的对象类型是 BuyTransaction。基cL造期_(d)虚函C来不?x)向下匹配(go downQ到zcR取而代之的是,那个对象的行为就好像它的cd是基cR非正式地讲Q?span style="COLOR: #ff0000">基类构造期_(d)虚函数禁?/span>?q个表面上看h匪夷所思的行ؓ(f)存在一个很好的理由。因为基cȝ构造函数在zcL造函C前执行,当基cL造函数运行时Q派生类数据成员q没有被初始化。如果基cL造期间调用的虚函数向下匹配(go downQ到zc,zcȝ函数理所当然?x)涉及(qing)到本地数据成员Q但是那些数据成员还没有被初始化。这׃(x)为未定义行ؓ(f)和?zhn)之晚矣的调试噩梦开了一张通行?/span>。调用涉?qing)到一个对象还没有被初始化的部分自然是危险的,所?C++ 告诉你此路不通?br>      在实际上q有比这更多的更深层ơ的原理。在zcd象的基类构造期_(d)对象的类型是那个基类的?span style="COLOR: #ff0000">不仅虚函C(x)解析到基c,而且语言中用到运行时cd信息Qruntime type informationQ的配gQ例如,dynamic_cast?typeidQ,也会(x)对象视为基cȝ型?/span>在我们的例子中,?Transaction 构造函数运行初始化 BuyTransaction 对象的基c部分时Q对象的cd?Transaction。C++ 的每一个配件将以如下眼光来看待它,q对它生这L(fng)感觉Q对象的 BuyTransaction Ҏ(gu)的部分还没有被初始化Q所以安全的对待它们的方法就是视若无睏V在zcL造函数运行之前,一个对象不?x)成Z个派生类对象?br>
  同样的原因也适用于析构过E。一旦派生类析构函数q行Q这个对象的zcL据成员就被视为未定义的|所?C++ 将它们视ؓ(f)不再存在。在q入基类析构函数Ӟ对象成Z个基cd象,C++ 的所有配件——虚函数Qdynamic_casts {——都如此看待它?

ivy-jie 2009-05-18 17:26 发表评论
]]>
虚函数实现机?/title><link>http://www.shnenglu.com/ivy-jie/articles/83250.html</link><dc:creator>ivy-jie</dc:creator><author>ivy-jie</author><pubDate>Mon, 18 May 2009 01:26:00 GMT</pubDate><guid>http://www.shnenglu.com/ivy-jie/articles/83250.html</guid><wfw:comment>http://www.shnenglu.com/ivy-jie/comments/83250.html</wfw:comment><comments>http://www.shnenglu.com/ivy-jie/articles/83250.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ivy-jie/comments/commentRss/83250.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ivy-jie/services/trackbacks/83250.html</trackback:ping><description><![CDATA[    C++中的虚函数的作用主要是实C多态的机制。关于多态,而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子cȝ成员函数。这U技术可以让父类的指针有“多种形?#8221;Q这是一U泛型技术。所谓泛型技术,说白了就是试图用不变的代码来实现可变的法。比如:(x)模板技术,RTTI技术,虚函数技术,要么是试囑ց到在~译时决议,要么试图做到q行时决议?br>1 虚函数表<br>    虚函敎ͼVirtual FunctionQ是通过一张虚函数表(Virtual TableQ来实现的。简UCؓ(f)V-Table?在这个表中,L要一个类的虚函数的地址表,q张表解决了l承、覆盖的问题Q保证其容真实反应实际的函数。这P在有虚函数的cȝ实例中这个表被分配在?q个实例的内存中Q所以,当我们用父类的指针来操作一个子cȝ时候,q张虚函数表显得由为重要了Q它?yu)像一个地图一P指明了实际所应该调用的函数? <p>    q里我们着重看一下这张虚函数表。在C++的标准规D明书中说刎ͼ~译器必需要保证虚函数表的指针存在于对象实例中最前面的位|(q是Z保证正确取到虚函数的偏移量)(j)?q意味着我们通过对象实例的地址得到q张虚函数表Q然后就可以遍历其中函数指针Qƈ调用相应的函数?</p> 2 代码Q?br>#include <stdio.h><br>#include <iostream.h><br>#include <stdlib.h><br>typedef void (*Fun) (void);<br>class Base{<br>public:<br> virtual void f() {cout<<"Base::f"<<endl;}<br> virtual void g() {cout<<"Base::g"<<endl;}<br> virtual void h() {cout<<"Base::h"<<endl;}<br>};<br>void main(int argc,char * argv[])<br>{<br>  Base b;<br>  Fun pFun = NULL;<br>  int *var1= (int *)&b;<br>  cout<<"虚函数表地址:"<<var1<<endl; //(int*)(&b)<br>  int *var2 = (int*)*(int*)(&b);<br>  cout<<"虚函数表-W一个函数地址:"<< var2 << endl;//(int*)*(int*)(&b)<br>  //Invoke the first virtual function<br>  pFun = <span style="COLOR: red">(Fun)*((int*)*(int*)(&b)+0);</span> //f()<br>  pFun();<br>  pFun = (Fun)*((int*)*(int*)(&b)+1); //g()<br>  pFun();<br>  pFun = (Fun)*((int*)*(int*)(&b)+2); // h() <br>  pFun();<br>}<br>//l果<br>虚函数表地址:0x0012FF7C<br>虚函数表-W一个函数地址:0x0042804C<br>Base::f<br>Base::g<br>Base::h<br> <img src ="http://www.shnenglu.com/ivy-jie/aggbug/83250.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ivy-jie/" target="_blank">ivy-jie</a> 2009-05-18 09:26 <a href="http://www.shnenglu.com/ivy-jie/articles/83250.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>函数指针实现回调http://www.shnenglu.com/ivy-jie/articles/83247.htmlivy-jieivy-jieMon, 18 May 2009 00:40:00 GMThttp://www.shnenglu.com/ivy-jie/articles/83247.htmlhttp://www.shnenglu.com/ivy-jie/comments/83247.htmlhttp://www.shnenglu.com/ivy-jie/articles/83247.html#Feedback0http://www.shnenglu.com/ivy-jie/comments/commentRss/83247.htmlhttp://www.shnenglu.com/ivy-jie/services/trackbacks/83247.html  p是指向某函数的指针,该函数无输入参数Q返回值的cd为void。左边圆括弧里星号后的就是指针变量名。有了指针变量便可以赋|值的内容是v名匹配的函数名和q回cd。例如:(x)

void func() 
{
/* do something */

p = func; 

p的赋值可以不同,但一定要是函数的地址Qƈ且v名和q回cd相同?br>
传递回调函数的地址l调用?br>
现在可以p传递给另一个函敎ͼ调用者)(j)- caller()Q它?yu)调用p指向的函敎ͼ而此函数名是未知的:(x)

void caller(void(*ptr)())
{
ptr(); /* 调用ptr指向的函?*/ 
}
void func();
int main()
{
p = func; 
caller(p); /* 传递函数地址到调用?*/
}

    如果赋了不同的值给pQ不同函数地址Q,那么调用者将调用不同地址的函数。赋值可以发生在q行Ӟq样使你能实现动态绑定?br>
调用规范

    到目前ؓ(f)止,我们只讨Z函数指针?qing)回调而没有去注意ANSI C/C++的编译器规范。许多编译器有几U调用规范。如在Visual C++中,可以在函数类型前加_cdeclQ_stdcall或者_pascal来表C其调用规范Q默认ؓ(f)_cdeclQ。C++ Builder也支持_fastcall调用规范。调用规范媄(jing)响编译器产生的给定函数名Q参C递的序Q从叛_左或从左到右Q,堆栈清理责QQ调用者或者被调用者)(j)以及(qing)参数传递机Ӟ堆栈QCPU寄存器等Q?br>
    调用规范看成是函数cd的一部分是很重要的;不能用不兼容的调用规范将地址赋值给函数指针。例如:(x)

// 被调用函数是以int为参敎ͼ以int回?br>__stdcall int callee(int); 

// 调用函数以函数指针ؓ(f)参数
void caller( __cdecl int(*ptr)(int)); 

// 在p中企囑֭储被调用函数地址的非法操?br>__cdecl int(*p)(int) = callee; // 出错


    指针p和callee()的类型不兼容Q因为它们有不同的调用规范。因此不能将被调用者的地址赋值给指针pQ尽两者有相同的返回值和参数列?

ivy-jie 2009-05-18 08:40 发表评论
]]>
þþƷƷ| þþþavר | ¾þþþa| ȾþùŷһƷ| 99þѹػ| þݺҹҹavapp | ޹Ƶþ| ŷþۺϾɫۺ| þ91ƷۺϹҳ| 91þۺ| 2021˾Ʒþ| 91Ʒþþþþù۲| þùƷ99Ʒ987| þþƷ| þ޾ƷĻ| þۺ97ɫ| þ99Ʒһ| Ʒþþþþ޾Ʒ| þ99ƷСѼ| ɫAVԾþþþþ| ҹþþӰԺ| ޾ƷþþþþðĦ| ޾ƷƬþ| þݺҹҹվ | þùƷվ| ŷ龫Ʒþþþþþþžž | ʵҶ԰׾ʾþ| Ʒþþþþþþþ| þ޹Ʒ| 㽶þҹɫƷ2020| þþþ޾Ʒվ| þùɫAVѿ| Ʒһþò| þŮˬŮˬ| 뾫Ʒþһ| 69Ʒþþþ9999APGF| ۺþþ| ѾþþƷѾѾ| þþƷУСŮ| þùƷþþ| ղƷaëƬþ|