面向对象(一)

面向对象的基本特征:
1、抽象:从具体到一半的过程。抓住事物的本质,而不是内部的具体实现细节。

2、封装:把对象的属性和操作结合在一起,构成一个独立的对象;对外提供一定的接口,在对象之外只能通过接口对对象进行操作;封装增加了对象的独立性,从而保证了数据的可靠性;

3、继承:表达了对象的一般与特殊的关系。特殊类的对象具有一般类的全部属性和服务。当定义一个类后,又需要定义一个新
类,这个新类与原来的类相比,只是增加或修改了部分属性和操作,这时可以用原来的类派生出新类,新类中只需要描述自己所特有的属性和操作。继承简化了对问题的描述,大大提高了程序的可重用性。

4、多态:同一个消息被不同的对象接收时,产生不同的结果,即实现同一个接口,不同方法。一般类中定义的属性和服务,在特
殊类中不改变其名字,但通过各自不同的实现后,可以具有不同的数据类型或不同的行为。

继承和多态性组合,可以生成很多相似但又独一无二的对象。继承性使得这些对象可以共享许多相似特性,而多态又使同一个操作对不同对象产生不同表现形式。这样不仅提高了程序设计的灵活性,而且减轻了分别设计的负担。

内联函数:
内联函数能够提高运行效率,将代码直接嵌入到调入的地方,从而减少了函数调用的开销。程序的体积会增大,以空间换时间。
两种方法实现内联:1、在类中声明,在实现的时候加上inline关键字; 2、在类中直接实现,即使没有加上inline关键字

函数可进行重载,要求相同的作用域。成员函数可以进行重载,要求在类作用域当中。

c++中结构体可以有成员函数。
class与struct的区别:struct默认的是私有成员,struct默认是共有成员。

类的作用域:
1、每个类都定义了自己的作用域称为类作用域;
2、类作用域中说明的标识符只在类中可见。

类作用域:作用域在在类内部
块作用域:作用域在花括号内的,不会影响块作用域外部的变量
文件作用域:在任何代码之外的作用域,在定义的地方到文件结尾有效
函数原型作用域:int Add(int a ,int b) a,b作用域为函数原型作用域,所以在函数定义和函数声明的地方可以同名
函数作用域:在函数内部,主要用于goto语句

前向声明:
1、c++中类必须先定义,才能够实例化。
2、两个类需要相互引用形成一个“环形”引用时,无法先定义适用。这时候需要前向引用。
3、前向声明的类不能实例化

类的嵌套,嵌套类被隐藏在外围类中,该类名只能在外围类中使用。

//类的嵌套
class Outer
{
    class Inner
    {
    public:
        void fun()
        {
            cout << "Inner::fun..." << endl;
        }
    };
public:
    Inner obj_;
    void Fun()
    {
        cout << "Outer::fun.." << endl;
        obj_.fun();
    }
};

int main()
{
    Outer o_;
    o_.Fun();
    system("Pause");
    return 0;
}

如果在外围类的作用域使用该类名时,需要加类的作用域运算符。嵌套类的成员函数可以定义在外围类之外定义。

class Outer
{
    class Inner
    {
    public:
        void fun();
    };
public:
    Inner obj_;
    void Fun()
    {
        cout << "Outer::fun.." << endl;
        obj_.fun();
    }
};

void Outer::Inner::fun()
{
    cout << "Inner::fun.." << endl;
}
int main()
{
    Outer o_;
    o_.Fun();
    system("Pause");
    return 0;
}

嵌套类的成员函数对外围类的成员没有访问权,反之亦然。

类也可以定义在函数体内,这样的类被称为局部类。局部类只在定义它的局部域内可见。
局部类的成员函数必须被定义在函数类体内。
局部类中不能有静态成员。

void fun()
{
    class LocalClass
    {
    public:
        void Init(int num)
        {
            num_ = num;
        }
        void Display()
        {
            cout << "num_=" << num_ << endl;
        }
    private:
        int num_;
        //static int num2_;  // 局部类中不能定义静态成员
    };
    LocalClass LC_;  
    LC_.Init(5);
    LC_.Display();
}

构造函数:
构造函数是特殊的成员函数;
创建类的新对象,系统自动会调用析构函数;
构造函数是为了保证对象的每个数据成员都被正确初始化;

1、函数名与类名完全相同
2、不能定义构造函数的类型(返回类型),也不能使用void
3、通常构造函数被声明为共有的,否则不能被显式的调用。私有构造函数也有其用途。
4、构造函数可以有任意类型和任意个数的参数,一个类可以有多个构造函数(重载)

当没有声明构造函数,类中会自动生成不带参数的构造函数。当声明带参数的构造函数时,类就不会自动生成不带参数的构造函数,此时,可以显式的声明构造函数。

全局对象的构造先于main函数

Test t(10);  //全局对象的构造先与main函数
int main()
{
    cout << "main start.." << endl;
}
image.png

在栈区创建的对象,在生存周期结束时会自动调用析构函数,在堆上创建的对象,要由程序员显式调用delete来释放,同时调用析构函数。

//全局对象的构造先与main函数
int main()
{
    Test t[2] = { 10,20 };
    Test *p1 = new Test(2);
    delete p1;  //delete显式调用该释放对象,同时调用析构函数
    Test *p2 = new Test[2];
    delete[] p2;
    cout << "main start.." << endl;
}
image.png

构造函数作用:
初始化;
转换构造函数;

int main()
{
    Test t1(10);  //带一个参数的构造函数,充当的是普通构造函数的功能
    t1 = 30;   //将20这个整数赋值给t1对象
                //1、调用转换构造函数将20这个整数转换成类类型,生成一个临时对象
                //2、将临时对象赋值给t对象

    Test t2 = 20; //等价于Test t2(20); 这里的不是运算符,表示初始化
    
    cout << "main start.." << endl;
    return 0;
}
image.png
class Test
{
public:
    void Display();
    Test& operator=(const Test& other);
    Test();
    Test(int num);
    ~Test();
private:
    int num_;
};



Test& Test::operator=(const Test& other)
{
    num_ = other.num_;
    cout << "Test::operator=" << endl;
    return *this;
}


int main()
{
    Test t1(10);  //带一个参数的构造函数,充当的是普通构造函数的功能
    t1 = 30;   //将20这个整数赋值给t1对象  
                //1、调用转换构造函数将20这个整数转换成类类型,生成一个临时对象,此时的=已经被重载
                //2、将临时对象赋值给t对象,再销毁新建的临时变量

    Test t2 = 20; //等价于Test t2(20); 这里的不是运算符,表示初始化
    
    cout << "main start.." << endl;
    return 0;
}
image.png

explicit,只提供给类的构造函数使用的关键字
编译器不会把声明为explcit的构造函数用于隐式转换,它只能在程序diamante中显式创建对象

在构造函数初始化列表进行数据成员初始化

Clock::Clock(int hour , int minute ,int second :hour_(hour),minute_(minute),second_(second))

构造函数的执行分为两个阶段:
1、初始化段
2、普通计算段

class Object
{
public:
    Object(int num) :num_(num) //数据成员初始化
    {
        cout << "Object..." << endl;
    }
    ~Object()
    {
        cout << "~Object..." << endl;
    }
private:
    int num_;
};

class Container
{
public:
    Container(int obj1 = 0, int obj2 = 0) :obj1_(obj1), obj2_(obj2)  //初始化列表中进行初始化
    {
        cout << "Container..." << endl;
    }
    ~Container()
    {
        cout << "~Container..." << endl;
    }
private:
    Object obj1_; //没有默认的构造函数,需要在之前对构造函数进行初始化赋值
    Object obj2_;//缺省传参,使用默认值
};

const数据成员只能在构造函数初始化列表中进行初始化
引用成员也只能在构造函数初始化列表中进行初始化
对象成员(对象所对应的类没有默认构造函数)的初始化,也只能在构造函数初始化列表中进行

class Object
{
public:
    Object(int num) :num_(num),knum_(30),refnum_(num_) //对象成员初始化
    {
        cout << "Object..." << endl;
    }
    ~Object()
    {
        cout << "~Object..." << endl;
    }
private:
    int num_;
    const int knum_;
    int &refnum_;
};


const只能对每个对象来说是常量,不适用所有对象,枚举则使用于所有对象

class Object
{
public:
    enum E_TYPE
    {
        TYPE_A = 100,  //枚举只有逗号分隔
        TYPE_B = 200
    };

public:
    Object(int num) :num_(num),knum_(30),refnum_(num_) //对象成员初始化
    {
        cout << "Object..." << endl;
    }
    ~Object()
    {
        cout << "~Object..." << endl;
    }
    void Displayknum()
    {
        cout << "knum_=" << knum_ << endl;
    }
private:
    int num_;
    const int knum_;
    int &refnum_;
};
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • C++ 面向对象 c++创建对象的时候如果使用new运算符,将会返回返回一个指针,指向堆中的内存地址 类,对象类定...
    小小小8021阅读 308评论 0 0
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,869评论 2 9
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,542评论 1 51
  • C++类和对象 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心...
    863cda997e42阅读 697评论 0 4
  • 能在巴学园工作和学习该是多么幸福呀!能有一个这样平易近人的校长该是多么难忘呀!看完《窗边的小豆豆》,那阵阵笑声...
    二爷阅读 673评论 0 0