• C++知识点


    1、直接使用结构体做为参数

    struct sclass            
    {            
        int a;        
        int b;        
    };            
    int Plus(int a,int b)            
    {            
        return a+b;        
    }            
                
    int main(int argc, char* argv[])            
    {            
        sclass s;        
        s.a = 10;        
        s.b = 20;        
                
        int x = Plus(s.a,s.b);        
                
        printf("%d
    ",x);        
        return 0;        
    }            

    总结:

    将结构体直接做为参数传递的时候,传递的是整个结构体.

    反汇编:

    sub esp,10h
    mov eax,esp
    mov ecx,dword ptr [ebp-10h]
    mov dword ptr [eax],ecx
    mov edx,dword ptr [ebp-0Ch]
    mov dword ptr [eax+4],edx
    mov ecx,dword ptr [ebp-8]
    mov dword ptr [eax+8],ecx
    mov edx,dword ptr [ebp-4]
    mov dword ptr [eax+0Ch],edx
    call @ILT+35(Plus) (00401028)
    add esp,10h

    2、传递结构体指针

    struct sclass            
    {            
        int a;        
        int b;        
        int c;        
        int d;        
    };            
    int Plus(sclass* sc)            
    {            
        return sc->a+sc->b;        
    }            
    int main(int argc, char* argv[])            
    {            
        sclass s;        
        s.a = 10;        
        s.b = 20;        
                
        int x = Plus(&s);        
                
        printf("%d
    ",x);        
        return 0;        
    }            

    反汇编:

    mov dword ptr [ebp-10h],0Ah
    mov dword ptr [ebp-0Ch],14h
    lea eax,[ebp-10h]
    push eax
    call @ILT+40(Plus) (0040102d)
    add esp,4

    3、函数可以放在结构体里面,也可以放在结构体外面

    struct sclass                
    {                
        int a;            
        int b;            
        int c;            
        int d;            
                    
        int Plus(sclass* sc)            
        {            
            return sc->a+sc->b;        
        }            
    };                
                    

    探测:通过sizeof来探测将函数放在里面与外面结构体的大小有什么变化?

    4、函数放在里面如何使用的问题 观察反汇编:

    struct sclass                
    {                
        int a;            
        int b;            
        int c;            
        int d;            
                    
        int Plus(sclass* sc)            
        {            
            return sc->a+sc->b;        
        }            
    };                
                    
    int main(int argc, char* argv[])                
    {                
        sclass s;            
        s.a = 10;            
        s.b = 20;            
                    
        int x = s.Plus(&s);            
                    
        printf("%d %x
    ",x,sizeof(s));            
        return 0;            
    }                
                    

    注意观察反汇编:

    1、参数传递

    2、堆栈平衡

    有没有发现什么问题?

    5、封装、类、成员函数

        struct sclass                
        {                
            int a;            
            int b;            
            int c;            
            int d;            
                        
            int Plus()            
            {            
                return a+b;        
            }            
        };                
                        
        int main(int argc, char* argv[])                
        {                
            sclass s;            
            s.a = 10;            
            s.b = 20;            
                        
            int x = s.Plus();            
                        
            printf("%d %x
    ",x,sizeof(s));            
                        
            return 0;            
        }                

    封装:

    1、将函数定义到结构体内部,就是封装.

    2、编译器会自动传递结构体的指针给函数.

    类:

    带有函数的结构体,称为类.

    成员函数:

    结构体里面的函数,称为成员函数.


     6、什么是this指针?

    struct sclass            
    {            
        int a;        
        int b;        
        int c;        
        int d;        
                
        int Plus()        
        {        
            return a+b;    
        }        
    };            
                
                
    sclass s;            
                
    s.Plus();            

    观察反汇编:

    lea ecx,[ebp-10h]
    call @ILT+90(Plus) (0040105f)

    this指针的特点:

    1、你用或者不用,它就在那里

    2、参数个数确定的时候,用ecx来传递

    3、参数个数不确定的时候,最后一个传递(参见不定长参数)

    4、this指针不能做++ -- 等运算,不能重新被赋值.

    5、this指针不占用结构体的宽度.

    //显示使用this指针                
                    
    struct sclass                
    {                
        int a;            
        int b;            
                    
        void Init(int a,int b)            
        {            
            this->a = a;        
            this->b = b;        
        }            
        void Print()            
        {            
            printf("%d %d",a,b);        
        }            
                    
    };                
                    
    sclass s;                
                    
    s.Init(1,2);                
                    
    s.Print();                

    7、构造函数

        struct Person            
        {            
            int age;        
            int level;        
            Person()        
            {        
                printf("Person对象创建了
    ");    
            }        
            Person(int age,int level)        
            {        
                this->age = age;    
                this->level = level;    
            }        
            void Print()        
            {        
                printf("%d-%d
    ",age,level);    
            }        
        };            
                    

    构造函数的特点:

    1、与类同名

    2、没有返回值

    3、创建对象的时候执行

    4、主要用于初始化

    5、可以有多个(最好有一个无参的),称为重载 其他函数也可以重载

    6、编译器不要求必须提供

    8、析构函数

    析构函数的特点:

    1、只能有一个析构函数,不能重载

    2、不能带任何参数

    3、不能带返回值

    4、主要用于清理工作

    5、编译器不要求必须提供

        #include "malloc.h"            
                    
        struct Person            
        {            
            int age;        
            int level;        
            char* arr;        
            Person()        
            {        
                printf("无参构造函数执行了...");    
            }        
            Person(int age,int level)        
            {        
                printf("有参构造函数执行了...");    
                this->age = age;    
                this->level = level;    
                arr = (char*)malloc(1024);    
            }        
            ~Person()        
            {        
                printf("析构函数执行了...");    
                free(arr);    
                arr = NULL;    
            }        
            void Print()        
            {        
                printf("%d-%d
    ",age,level);    
            }        
        };            

    9、继承

    1、观察反汇编        
            
    struct Person        
    {        
        int age;    
        int sex;    
    };        
    struct Teacher        
    {        
        int age;    
        int sex;    
        int level;    
        int classId;    
    };        
    struct Student        
    {        
        int age;    
        int sex;    
        int code;    
        int score;    
    };        
            
    Teacher t;        
            
    t.age = 1;        
    t.sex = 2;        
    t.level = 3;        
    t.classId = 4;        
            
    printf("%d
    ",sizeof(t));        
            

    观察反汇编:

    mov dword ptr [ebp-10h],1
    mov dword ptr [ebp-0Ch],2
    mov dword ptr [ebp-8],3
    mov dword ptr [ebp-4],4
    push 10h
    push offset string "%d " (0042201c)
    call printf (004010e0)
    add esp,8

    Student s;        
            
    s.age = 1;        
    s.sex = 2;        
    s.code = 3;        
    s.score = 4;        
            
    printf("%d
    ",sizeof(s));        

    mov dword ptr [ebp-10h],1
    mov dword ptr [ebp-0Ch],2
    mov dword ptr [ebp-8],3
    mov dword ptr [ebp-4],4
    push 10h
    push offset string "%d " (0042201c)
    call printf (004010e0)
    add esp,8

        2、改变写法:        
                
                
        struct Person        
        {        
            int age;    
            int sex;    
        };        
        struct Teacher:Person        
        {        
            int level;    
            int classId;    
        };        
        struct Student:Person        
        {        
            int code;    
            int score;    
        };        
                
    Teacher t;            
                
    t.age = 1;            
    t.sex = 2;            
    t.level = 3;            
    t.classId = 4;            
                
    printf("%d
    ",sizeof(t));            
                

    观察反汇编:

    mov dword ptr [ebp-10h],1
    mov dword ptr [ebp-0Ch],2
    mov dword ptr [ebp-8],3
    mov dword ptr [ebp-4],4
    push 10h
    push offset string "%d " (0042201c)
    call printf (004010e0)
    add esp,8

    Student s;        
            
    s.age = 1;        
    s.sex = 2;        
    s.code = 3;        
    s.score = 4;        
            
    printf("%d
    ",sizeof(s));        

    mov dword ptr [ebp-10h],1
    mov dword ptr [ebp-0Ch],2
    mov dword ptr [ebp-8],3
    mov dword ptr [ebp-4],4
    push 10h
    push offset string "%d " (0042201c)
    call printf (004010e0)
    add esp,8

    总结: 

    1、什么是继承?

    继承就是数据的复制

    2、为什么要用继承?

    减少重复代码的编写

    3、Person 称为父类或者基类

    4、Teacher、Student称为子类或者派生类

    5、t和s可以称为对象或者实例.

    6、可以用父类指针指向子类的对象.

    多层继承:        
            
    struct X        
    {        
        int a;    
        int b;    
    };        
    struct Y:X        
    {        
        int c;    
        int d;    
    };        
    struct Z:Y        
    {        
        int e;    
        int f;    
    };        
            
            
    Z z;        
            
    z.a = 1;        
    z.b = 2;        
    z.c = 3;        
    z.d = 4;        
    z.e = 5;        
    z.f = 6;        
            
    printf("%d
    ",sizeof(z));        
            
            
            
            
            
    struct X        
    {        
        int a;    
        int b;    
    };        
    struct Y:X        
    {        
        int a;    
        int d;    
    };        
    struct Z:Y        
    {        
        int e;    
        int f;    
    };        
            
            
            
    Z z;        
            
    z.X::a = 1;        
    z.b = 2;        
    z.Y::a = 3;        
    z.d = 4;        
    z.e = 5;        
    z.f = 6;        
            
    printf("%d
    ",sizeof(z));        
    printf("%d
    ",z.X::a);        
    printf("%d
    ",z.b);        
    printf("%d
    ",z.Y::a);        
    printf("%d
    ",z.d);        
    printf("%d
    ",z.e);        
    printf("%d
    ",z.f);        

    观察反汇编:

    mov dword ptr [ebp-18h],1
    mov dword ptr [ebp-14h],2
    mov dword ptr [ebp-10h],3
    mov dword ptr [ebp-0Ch],4
    mov dword ptr [ebp-8],5
    mov dword ptr [ebp-4],6
    push 18h
    push offset string "%d " (0042201c)
    call printf (004010e0)
    add esp,8

    多重继承:        
            
    struct X        
    {        
        int a;    
        int b;    
    };        
    struct Y        
    {        
        int c;    
        int d;    
    };        
    struct Z:X,Y        
    {        
        int e;    
        int f;    
    };        
            
            
    Z z;        
            
    z.a = 1;        
    z.b = 2;        
    z.c = 3;        
    z.d = 4;        
    z.e = 5;        
    z.f = 6;        
            
    printf("%d
    ",sizeof(z));        
            
    
    3、继承的特性        
            
            
    struct X        
    {        
        int a;    
        int b;    
    };        
    struct Y        
    {        
        int a;    
        int d;    
    };        
    struct Z:X,Y        
    {        
        int e;    
        int f;    
    };        
            
            
    Z z;        
            
    z.X::a = 1;        
    z.b = 2;        
    z.Y::a = 3;        
    z.d = 4;        
    z.e = 5;        
    z.f = 6;        
            
    printf("%d
    ",sizeof(z));        
    printf("%d
    ",z.X::a);        
    printf("%d
    ",z.b);        
    printf("%d
    ",z.Y::a);        
    printf("%d
    ",z.d);        
    printf("%d
    ",z.e);        
    printf("%d
    ",z.f);        
            

    观察反汇编:


    mov dword ptr [ebp-18h],1
    mov dword ptr [ebp-14h],2
    mov dword ptr [ebp-10h],3
    mov dword ptr [ebp-0Ch],4
    mov dword ptr [ebp-8],5
    mov dword ptr [ebp-4],6
    push 18h
    push offset string "%d %x " (0042201c)
    call printf (004010e0)
    add esp,8


    总结:

    一个子类可以有多个父类,即多重继承

    观察反汇编:


    mov dword ptr [ebp-18h],1
    mov dword ptr [ebp-14h],2
    mov dword ptr [ebp-10h],3
    mov dword ptr [ebp-0Ch],4
    mov dword ptr [ebp-8],5
    mov dword ptr [ebp-4],6
    push 18h
    push offset string "%d %x " (0042201c)
    call printf (004010e0)
    add esp,8

    总结:

    1、多重继承增加了程序的复杂度,容易出错

    2、微软建议使用单继承,如果需要多重继承可以改为多层继承


    10、将定义与实现分离,代码会有更好的可读性

    xxx.h 头文件中                
                    
    struct Test                
    {                
        int x;            
        int y;            
        int z;            
                    
        void Init(int x,int y,int z);            
        void Function1();            
        void Function2();            
        void Function3();            
    };                
                    
                    
    xxx.cpp                
                    
    void Test::Init(int x,int y,int z)                
    {                
        this->x = x;            
        this->y = y;            
        this->z = z;            
    }                
    void Test::Function1()                
    {                
        printf("Function1:%x
    ",x);            
    }                
    void Test::Function2()                
    {                
        printf("Function2:%x
    ",y);            
    }                
    void Test::Function3()                
    {                
        printf("Function3:%x
    ",z);            
    }                
                    

    特别说明:

    1、xxx.h 只是一个文件,可以是任何的后缀名,如果你愿意,
    可以叫xxx.exe

    2、#include 的作用只是把里面的内容复制过来 仅此而已.

    如:#include "abc.exe"

    3、xxx.h 与 xxx.cpp并不要求一定同名

    11、public private的使用

    public的意思是,这个成员哪里都可以用,不用担心被修改,所以,一旦发布成public的成员,是不能够改名字的.

    private的意思是,这个成员只用于内部使用,不要在其他的地方使用.

    如下:                探测一:观察private成员是否有空间            
                                
    struct Test                printf("%d
    ",sizeof(Test));            
    {                            
    private:                探测二:直接使用private成员            
        int x;                        
    public:                Test t;            
        int y;             t.x = 10;            
    };                    t.y = 20;            
                                

    总结:

    1、对外提供的函数或者变量,发布成public的 但不能随意改动.

    2、可能会变动的函数或者变量,定义成private的 这样编译器会在使用的时候做检测.

    3、只有结构体内部的函数才可以访问private的成员.

    4、public/private可以修饰函数也可以修饰变量.

    private真的不能访问吗?

    struct Test            
    {            
    private:            
        int x;        
    public:            
        int y;        
        void Init(int x,int y)        
        {        
            this->x = x;    
            this->y = y;    
        }        
    };            
                    
    Test t;            
    t.Init(1,2);            
                
                
    int* p = (int*)&t;            
                
    int n = *p;            
                
    int m = *(p+1);            
                
    printf("%d %d
    ",n,m);            
                

    总结:

    private修饰的成员与普通的成员没有区别 只是编译器会检测.

    private修饰的成员只要自己的其他成员才能访问

    1、成员权限的区别:                        
                            
    class Base                        
    {                        
        int x;                    
        int y;                    
    };                        
                            
    int main(int argc, char* argv[])                        
    {                        
        Base base;                    
                            
        base.x = 10;                    
        base.y = 20;                    
                            
        return 0;                    
    }                        
                            
                            
    class与struct的区别:                        
                            
    编译器默认class中的成员为private 而struct中的成员为public                        
                            
    2、继承中的区别:            
                
                
    class Base            
    {            
    public:            
        int x;        
        int y;        
    };            
    class Sub:Base            
    {            
    public:            
        int a;        
        int b;        
    };            
    int main(int argc, char* argv[])            
    {            
        Sub sub;        
                
        sub.x = 1;  //无法访问        
        sub.y = 2;  //无法访问        
        sub.a = 3;        
        sub.b = 4;        
                
        return 0;        
    }            
        class Sub:private Base    
        {    
        public:    
            int a;
            int b;
        };    
            
        父类中的程序继承后变成private属性    
            
        如果不希望改变成员的属性:    
            
        class Sub:public Base    
        {    
        public:    
            int a;
            int b;
        };    
    private是否被继承            
                
                
    class Base            
    {            
    public:            
        Base()        
        {        
            x = 11;    
            y = 12;    
        }        
    private:            
        int x;        
        int y;        
    };            
    class Sub:Base            
    {            
    public:            
        int a;        
        int b;        
    };            
                
    int main(int argc, char* argv[])            
    {            
        Sub sub;        
        sub.a = 1;        
        sub.b = 2;        
                
        int* p = (int*)⊂        
                
                
        printf("%d
    ",sizeof(sub));        
        printf("%d
    ",*(p+0));        
        printf("%d
    ",*(p+1));        
        printf("%d
    ",*(p+2));        
        printf("%d
    ",*(p+3));        
                
        return 0;        
    }            

    总结:

    1、父类中的私有成员是会被继承的

    2、只是编译器不允许直接进行访问

     

  • 相关阅读:
    perf + 火焰图用法 小结
    忽略多年的地理基本知识
    windows7安装docker异常:looks like something went wrong in step ‘looking for vboxmanage.exe’
    我的选择
    CSS3 width的min/max-content、fill-available以及fit-content
    Redis入门与命令汇总
    javascript中的原型详解
    Promise实现及原理
    nodejs中的垃圾回收
    javascript中的闭包
  • 原文地址:https://www.cnblogs.com/louzi/p/11148721.html
Copyright © 2020-2023  润新知