天天看点

C++之类和对象(一)(一)面向对象编程介绍(二)类的封装(四)深拷贝与浅拷贝(五)对象初始化列表:(六)构造函数与析构函数调用的顺序:

(一)面向对象编程介绍

1什么是面向对象:

面向对象将系统看成通过交互作用用来完成特定功能对象的集合,每个对象用自己的方法来管理数据,也就是说只有对象内部的代码能够操作对象内部的数据。

2面向过程的缺点:

不容易维护,灵活性差,不容易扩展,更谈不上复用,由于客户的需求多变,导致程序员加班加点,甚至整个项目经常返工。

3面向对象的优点:

通过,继承、封装、多态降低程序的耦合度,并结合设计模式让程序更容易修改和扩展,并且易于复用。易维护,质量高,效率高,易扩展

但缺点就是运行效率会下降百分之十左右

4.面向对象的特点:

1)抽象性:抽象是人们认识事物的一种方法,抓住事物本质,而不是内部具体实现的操作与步骤

2)封装性:1°封装是指按照信息屏蔽的原则,把对象的属性与方法(操作)放在一起,构成一个独立的对象

                  2°通过限制对属性的操作和访问权限,可以将信息隐藏在对象内部,对外提供一定的接口,在对象之外只能通过这个接口对对象进行操作

                  3°封装性增加了对象的独立性,从而保证了数据的可靠性

                  4°外部对象不能直接操作对象的属性,只能使用对象提供的服务

3)继承性:1°继承表达了对象的一般与特殊关系,特殊类的对象具有一般类的全部属性和服务

                  2°当定义了一个类后,又定义的一个新类,这些新类与原来的类相比,只是增加或修改了部分属性与操作,这时可以用原来的类派生出一个新类,新类中只描  述自己所特有的属性与操作即可。

                  3°继承性大大简化了对问题的描述,大大提高了程序的可重用性,从而提高了程序设计,修改,扩充的效率。

4)多态:   1°同一个消息被不同对象接收时,产生不同结果,即实现同一接口,不同方法

                  2°一般类中定义的属性与服务,在特殊类中不改变其名字,但通过各自不同的实现后,可以具有不同的数据类型或具有不同的行为

(二)类的封装

1成员变量,C++中用于表示类属性的变量

2成员函数,C++中用于表示类行为的函数

3 C++中提供一个新的关键字 class, 用来定义类,使用方式和struct基本相同

4   类的访问控制关键字:对属性和方法的使用权限进行限制

    1° public  : 可以在类的内部和类的外部访问

    2° private : 可以在类的内部但不能在类的外部访问,没有权限修饰的成员和函数默认是private的

    3°protect :可以在类的内部访问,但不能在类的外部访问,用在继承里面

5   在用struct定义类时,所有成员的默认属性为public

     在用class定义类时,所有成员的默认属性为private

6. 类的声明与类的实现分开:类的声明放在头文件中,类的实现放在源文件中,使用去主函数调用即可

(三)对象的构造与析构

1.构造函数的定义:

1)C++中的类可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做构造函数;

2)构造函数在定义时可以有参数;

3)没有任何返回类型的声明。

2.析构函数的定义:

1)C++中的类可以定义一个特殊的成员函数清理对象,这个特殊的成员函数叫做析构函数  语法:~ClassName()

2)析构函数没有参数也没有任何返回类型的声明

3)析构函数在对象销毁时自动被调用

3.对象的构造与析构

1)拷贝构造函数的调用时机:

     1°Test t2 = t1;   // 用对象 t1 去初始化t2

     2°Test t2(t0);    // 用对象 t0 去初始化t2

     3°PrintObj(t0);   // 做函数参数的时候,实参到形参的转换会调用拷贝构造函数

     4°t1 = test();       // 函数返回值返回对象, 用匿名对象给其他对象进行赋值,复制完对象后匿名对象会被析构

2)默认构造函数:(二个特殊的构造函数)

1°默认无参构造函数

当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空

2°默认拷贝构造函数  

当类中没有定义拷贝构造函数时,编译器默认提供一个默认拷贝构造函数,简单的进行成员变量的值复制

3)构造函数规则:

     1° 当类中没有定义任何一个构造函数时,c++编译器会提供默认无参构造函数和默认拷贝构造函数

     2° 当类中定义了拷贝构造函数时,c++编译器不会提供无参数构造函数

     3° 当类中定义了任意的非拷贝构造函数(即:当类中提供了有参构造函数或无参构造函数),c++编译器不会提供默认无参构造函数

     4° 默认拷贝构造函数成员变量简单赋值

总结:只要你写了构造函数,那么你必须用。

4)构造析构阶段性总结 

     1° 构造函数是C++中用于初始化对象状态的特殊函数

     2° 构造函数在对象创建时自动被调用

     3° 构造函数和普通成员函数都遵循重载规则

     4° 拷贝构造函数是对象正确初始化的重要保证

     5° 必要的时候,必须手工编写拷贝构造函数 

(四)深拷贝与浅拷贝

1浅拷贝存在的问题:

1°默认复制构造函数可以完成对象的数据成员值简单的复制

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

2解决浅拷贝的方法:

深拷贝,自己写一个拷贝构造函数,重新再堆上在分配一个空间,即可。例如请看如下代码:

#include 
  
   
#include 
   
    
 
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;
}
   
  
           

(五)对象初始化列表:

1°初始化列表解决了一个类对象在其他类中无法初始化的问题

2°类成员中若有const修饰,必须在对象初始化的时候,给const int m 赋值

当类成员中含有一个const对象时,或者是一个引用时,他们也必须要通过成员初始化列表进行初始化,

因为这两种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。

3°C++中提供初始化列表对成员变量进行初始化

语法规则

Constructor::Contructor() : m1(v1), m2(v1,v2), m3(v3)

{

    // some other assignment operation

}

4°注意概念

初始化:被初始化的对象正在创建

赋值:被赋值的对象已经存在

5°注意:

成员变量的初始化顺序与声明的顺序相关,与在初始化列表中的顺序无关

初始化列表先于构造函数的函数体执行

(六)构造函数与析构函数调用的顺序:

1°当类中有成员变量是其它类的对象时,首先调用成员变量的构造函数,调用顺序与声明顺序相同;之后调用自身类的构造函数

2°析构函数的调用顺序与对应的构造函数调用顺序相反

c++

继续阅读