类和对象(C witch class)

类和对象(C witch class)

面向过程编程

面向对象编程

class 类

C++的复合数据类型

class Student
{
public:
    //成员函数(方法)
    void show();    //在类中声明
    void SetAge(int age);
    void SetName(std::string name);
private:
    //成员变量(属性)
    std::string m_name;  //为了避免与函数中的形参命名冲突,自己的成员前面一般加  _m
    int m_age;

};
//函数在类外定义,但注意,需要在函数前加类的声明,Student::  标明函数是Student类中
void Student::show()
{
    std::cout << "学生姓名:" << m_name << "  学生年龄:" << m_age << std::endl;
}
void Student::SetAge(int age)
{
    m_age = age;
}
void Student::SetName(std::string name)
{
    m_name = name;
}

1、属性和方法要放在一起

2、访问控制

private:私有权限 除本类外都不可访问

protected:保护权限 除本类和本类的子类外都不可访问

public:公有权限 都可访问

默认访问权限:私有权限

建议写法:对属性访问关闭,对方法访问开放

struct和class

就目前水平来说:只有一个区别,默认权限不同,class默认私有,struct默认公有

3、初始化和销毁

​ 构造函数:用来对成员变量进行初始化的函数

​ 形式:函数名和类名相同,无返回值

​ 缺省函数:如果没写构造函数,编译器会给类生成默认的构造函数

​ 如果写了自定义的带参构造,编译器就不会生成默认构造,就需要自己手动输入

//缺省构造(无参构造)
Student() {}//编译器生成类似函数<!--无参数,无实体-->
//带参构造函数
Student(std::string name,int age)
//拷贝构造函数
Student(Student& s) //为了避免在从实参传入形参过程中进行拷贝,调用拷贝构造造成无限递归,这里使用引用
{
    m_name = s.m_name;
    m_age = s.m_age;
}
//拷贝构造函数调用
Student s1=s;
Student s1(s);
//赋值运算符的重载
编译器自定义:inline Student &Student::operator=(const Student &)
手动定义:    void operator=(Student &s)
            {
            m_name = s.m_name;
            m_age = s.m_age;
            }
Student s={"zhangsan",21};
Student s1;
s1 = s;

//析构函数:无返回值,函数名和类名相同 函数名前加一个 ~  无参数
//自动调用
//析构函数不能重载
~Student(){}

构造函数是可以重载的

raii:

资源获取及初始化

ps:如果以后有很多指针,统一在构造里申请,在析构里释放,能避免很多段错误

浅拷贝问题:当类中有指针成员在构造里申请空间,在析构中释放,如果拷贝构造只是简单的地址拷贝,会导致两个对象中的指针成员指向同一块堆上内存,导致二次释放

class Test
{
    public:
    Test()
    {
        a = new int;
    }
    ~Test()
    {
        delete a;
    }
    private:
        int *a;
};
int main()
{
    Test t;
    Test t1;
    t1 = t;
    return 0;
}

深拷贝:指针成员不能进行简单的地址拷贝,进行内存拷贝

class Test
{
    public:
    Test()
    {
        std::cout << "构造函数" << std::endl;
        a = new int;
    }
    //深度拷贝
    Test(Test& t)
    {
        std::cout << "拷贝构造函数" << std::endl;
        a = new int;
        *a = *t.a;
    }
    void operator=(Test &t)
    {
        std::cout << "赋值运算符的重载" << std::endl;
        delete a;
        a = new int;
        *a = *t.a;
    }
    ~Test()
    {
        std::cout << "析构函数" << std::endl;
        delete a;
    }
    private:
        int *a;
};
int main()
{
    Test t;
    Test t1;
    t1 = t;
    return 0;
}

匿名周期

Test();//匿名对象:声明周期只有一行   是右值(将亡值也是右值)
Test t1 = Test();  //没有拷贝,只构造一个对象

//RVO优化:返回值优化
//返回局部对象,不会发生拷贝,而是直接夺取内存,少一次拷贝构造  ps:老版本编译器没有这个优化能力
//左值是不会优化的
Test func()
{
    Test t;
    return t;//返回局部变量,将亡值
}
int main()
{
    Test t1 = func();
    return 0;
}

static:

1、修饰局部变量

2、修饰全局变量

3、修饰成员变量:该变量由整个类共享

4、修饰成员函数:该函数不依赖任何对象进行调用

class Test
{
private:

public:
        static int a;//静态成员变量
    //不属于某个特定的对象,属于整个类
};
//不能在构造函数中初始化,只能在类外单独定义
int Test::a = 0;

在类中定义的静态变量,相当于静态全局区的变量在类中有一个声明,不属于那个类,所以也不能随着构造函数初始化,只能在类外单独定义,同时,sizeof(t)的时候a的大写也不被包含在内

class Test
{
    public:
    Test()
    {
        a++;
    }
    ~Test()
    {
        a--;
    }

public:
        static int a;//静态成员变量
    //不属于某个特定的对象,属于整个类
};
int Test::a = 0;
int main()
{
    Test *t1 = new Test;
    Test *t2 = new Test;
    delete t1;
    delete t2;
    std::cout << Test::a << std::endl;

    return 0;
}

在构造函数时加一,析构函数时减一,可以检验程序内存是否泄漏

静态成员函数:

class Test
{
    public:
    static void func()//静态成员函数
    //不需要依赖对象调用
    //普通成员变量不能使用
    //使用静态成员变量
    {
		a++;
    }
    static int a;
};
int main()
{
	Test::func();
}

Singleton:单例模式

单例模式:一个类只能创建一个对象

1、构造函数私有化

2、提供一个静态函数接口,返回对象指针

3、定义静态局部变量,返回变量指针

//单例模式:一个类只能创建一个对象
class Singleton
{
    public:
    static Singleton* GetInstance()
    {
        static Singleton s;//只初始化一次
        return &s;
    }
    void show()
    {
        std::cout << "helloworld\n";
    }
    private:
    Singleton(){}//构造函数私有化
};

int main()
{
    Singleton *s1 = Singleton::GetInstance();
    s1->show();
    return 0;
}

因为构造函数初始化后无法新建变量,但又需要获取一个变量所以利用静态函数静态变量的特性,可以通过整个类调用,用它来给一个变量。

this指针

class Test
{
    public:
    Test(int a)
    {
        std::cout << "构造函数" << std::endl;
        m_a = a;
    }
    void show()
    {
         //this指针:由编译器自己生成,指向当前对象
        std::cout <<this->m_a << std::endl;
    }
    private:
        int m_a;
};
int main()
{
    Test t1(1);
    Test t2(1);
    t1.show();
    return 0;
}

在类函数中无法辨别m_a是t1还是t2的,其实编译器会自己生成一个this对象,指向当前对象,使自己能够辨别

ps:静态成员函数没有this指针

const

const变量初始化:初始化列表

class Test
{
    //初始化列表 :在构造函数后加: 后更要定义的变量
    //const变量必须在初始化列表中初始化
    public:
    Test():a(0) //也可以 Test(int t):a(0),b(b); 常量也可以在初始化列表中初始化
    {
    }
    void show()
    {
        std::cout <<this->a << std::endl;
    }
    private:
       const int a;
};
int main()
{
    Test t;
    t.show();
    return 0;
}

const的应用:

class Test
{
    public:
        //修饰返回值:返回值不可修改(只有用指针或引用接才会生效)其他类型变量都是拿的值
        // const int& func()
        // {
        //     return a;
        // }
        //修饰形参:不可修改,保证传进来的数据的安全(指针和引用)
        // void func(const int &a)
        // {
        // }
        //常成员函数:类的成员变量不能修改 ps:但将成员变量用引用传进来则可以修改
        void func()const
        {
        }
    private:
        int a;
};
int main()
{
    Test t;
    // int a = t.func();
    // const int &b = t.func();
    return 0;
}

expilicit:

防止隐式转换

class Integer
{
    public:
       //防止隐式转换 由explicit定义的函数禁止隐式转换
        explicit Integer(int a):a(a)
        {
        }
        void show()
        {
            std::cout << a << std::endl;
        }
    private:
        int a;
};
int main()
{
    Integer i(10);
    i = 20;//  i=Integer(20)   构造函数的隐式转换:会把符合构造函数形式的变量变换成匿名对象
           //所以为了私有值避免值被修改,要用explicit定义
    i.show();
    return 0;
}

new delete 和malloc free?

1、new delete :关键字 malloc free: 库函数

2、new不需要计算内存大小 malloc要手动计算

3、new不需要强转指针 malloc需要

4、new不需要判断返回值,会抛异常 malloc会判返回值

5、new delete 会调用构造和析构函数 malloc free 不会

友元

友元函数

友元类:1、友元关系是单向的

​ 2、友元关系不能传递,不可继承

class Point
{
    public:
        Point():x(0),y(0) {}
        Point(int x, int y) : x(x), y(y) {}
        void show()
        {
            std::cout << "(" << x <<","<<y<< ")" << std::endl;
        }
        //友元函数声明 可以调用私有权限的成员,如果一个类中友元声明过多,会显得臃肿
        // friend double Distance(const Point &p1, const Point &p2);
        //声明友元类
        friend class Tool;
    private:
        int x;
        int y;
};
//工具类
class Tool
{
    public:
    static double Distance(const Point &p1, const Point &p2)//为了避免使用工具类还需要新建工具变量,用static
{
    return std::sqrt(std::pow((p1.x-p2.x),2)+std::pow((p1.y-p2.y),2));
}
};

int main()
{
    Point p1;
    p1.show();
    Point p2(1, 2);
    p2.show();
    std::cout << Tool::Distance(p1, p2) << std::endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值