类和对象

面向对象编程介绍
C++面向对象程序设计
面向将系统看成通过交互作用来完成特定功能的对象的集合,没个对象用自己的方法来管理数据,也就是说对象内部的代码能够操作对象内部的数据
面向对象的优点:
由活字印刷谈面向对象;
面向对象的好处
面向过程的缺点:
不容易维护,灵活性差,不容易扩展,更谈不上复用,由于客户的需求多变,导致程序员加班加点,甚至整个项目经常返工。
面向对象的优点:
通过,继承、封装、多态降低程序的耦合度,并结合设计模式让程序更容易修改和扩展,并且易于复用。
设计模式简介。
面向对象的特点:
抽象,封装,继承,多态。

类的封装
struct 和class的区别:
在用struct定义类时,所有成员的默认属性为public
在用class定义类时,所有成员的默认属性为private

类的声明和类的实现分开:
类的声明放在头文件中
类的实现放在源文件中
以及main的使用

对象的构造和析构:
构造函数:
1,C++中的类可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做构造函数
2 ,构造函数在定义时可以有参数;
3,没有任何返回类型的声明。
调用:
自动调用:一般情况下C++编译器会自动调用构造函数;
手动调用:在一些情况下则需要手工调用构造函数;

析构函数:
1, C++中的类可以定义一个特殊的成员函数清理对象,这个特殊的成员函数就叫做析构函数~className()
2:析构函数没有参数也没有任何返回类型的声明;
3.析构函数在对象销毁时自动被调用;

对象的构造和析构:
构造函数的分类调用:
无参构造:
有参数构造:
理解对象初始化和对象赋值的不同
Test t1(4,5);
Test t2 = Test(5,6); // 对象的初始化
t2 = t1; // 对象的赋值

赋值(拷贝)构造函数:
拷贝构造函数的调用时机:
1、Test t2 = t1; // 用对象 t1 去初始化t2
2、Test t2(t0); // 用对象 t0 去初始化t2
3、PrintObj(t0); // 做函数参数的时候
4、t1 = test(); // 函数返回值返回对象

using namespace std;

class Test
{
public:
Test() // 无参构造函数
{
m_a = 0;
m_b = 0;
cout << “无参构造函数调用” << endl;
}

Test(int a)
{
    m_a = 1;
    m_b = 2;
    cout << "有参构造函数调用1" << endl;
}

Test(int a, int b)   // 有参构造函数
{
    m_a = a;
    m_b = b;
    cout << "有参构造函数调用2" << endl;
}

Test (char *name)
{
    strcpy(m_name, name);
}

// 赋值构造函数(拷贝构造函数)
Test(const Test &obj)
{
    cout << "拷贝构造函数调用" << endl;
    m_a = obj.m_a + 100;
    m_b = obj.m_b + 100;
    strcpy(m_name, "hello");
}

~Test()
{
    cout << "析构函数调用: " << m_name << endl;
}

public:
void print()
{
cout << “m_a:” << m_a << endl;
cout << “m_b:” << m_b << endl;
}
private:
char m_name[20];
int m_a;
int m_b;
};

void PrintObj(Test obj)
{
obj.print();
}

Test test()
{
Test A(“name A”);
return A;
}

// 赋值构造函数 用一个对象去初始化另一个对象
int main()
{

if 0

Test t0 = Test(3,4);
Test t1 = Test(5,6);

{
    //1 拷贝构造函数调用 1
    Test t2 = t1; // 用对象 t1 去初始化t2
    t2.print();
}

{
    //2  拷贝构造函数调用 2
    Test t2(t0); // 用对象 t0 去初始化t2
    t2.print();
}

{
    //3 类对象当函数形参的时候,实参到形参的转换会调用拷贝构造函数
    PrintObj(t0);
}

endif

{
    //4 当函数的返回值是类对象的时候,用一个对象去接收后会调用拷贝构造函数
    test();

    // 用匿名对象初始化 t, 此时c++编译器直接将匿名对象转化成 t (从匿名转成有名字)
    //Test t = test();

    Test t1("name t1");
    // 用匿名对象给其他对象进行赋值,复制完对象后匿名对象会被析构
    t1 = test();
    t1.print();

}
return 0;

}

默认构造函数:
二个特殊的构造函数
1)默认无参构造函数
当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空
2)默认拷贝构造函数
当类中没有定义拷贝构造函数时,编译器默认提供一个默认拷贝构造函数,简单的进行成员变量的值复制。

析构函数的规则:
1)当类中没有定义任何一个构造函数时,c++编译器会提供默认无参构造函数和默认拷贝构造函数
2)当类中定义了拷贝构造函数时,c++编译器不会提供无参数构造函数
3)当类中定义了任意的非拷贝构造函数(即:当类中提供了有参构造函数或无参构造函数),c++编译器不会提供默认无参构造函数
4 )默认拷贝构造函数成员变量简单赋值
总结:只要你写了构造函数,那么你必须用。

构造析构阶段性总结
1)构造函数是C++中用于初始化对象状态的特殊函数
2)构造函数在对象创建时自动被调用
3)构造函数和普通成员函数都遵循重载规则
4)拷贝构造函数是对象正确初始化的重要保证
5)必要的时候,必须手工编写拷贝构造函数

深拷贝和浅拷贝:

浅拷贝问题分析

```
#include <iostream>
#include <string.h>

using namespace std;

class Name
{
public:
Name(const char *p)
{
m_len = strlen(p);
m_p = (char *)malloc(m_len + 1);
}

~Name()
{
    cout << "析构函数被调用" << endl;
    if (m_p != NULL)
    {
        free (m_p);
        m_p = NULL;
        m_len = 0;
    }
    cout << "析构函数执行结束" << endl;
}

private:
char *m_p;
int m_len;
};

int main()
{
{
Name name1(“xiaoming”);
Name name2 = name1;
}

return 0;

}

对象的数据资源是由指针指示的堆时,默认复制构造函数仅作指针值复制

浅拷贝的问题解决方法:
我们引入一个深拷贝:



using namespace std;

class Name
{
public:
    Name(const char *p)
    {
        m_len = strlen(p);
        m_p = (char *)malloc(m_len + 1);
    }

    // 解决浅拷贝的方案:手动编写拷贝构造函数,进行深拷贝
    Name (const Name &obj)
    {
        m_len = obj.m_len;
        m_p = (char *)malloc(m_len + 1);
        strcpy (m_p, obj.m_p);
    }

    ~Name()
    {
        cout << "析构函数被调用" << endl;
        if (m_p != NULL)
        {
            free (m_p);
            m_p = NULL;
            m_len = 0;
        }
        cout << "析构函数执行结束" << endl;
    }

private:
char *m_p;
int m_len;
};

int main()
{
{
Name name1(“xiaoming”);
Name name2 = name1;
}

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值