C++基础入门--C++类和对象总结
小职 2021-11-08 来源 :网络 阅读 571 评论 0

摘要:本文主要是C++基础入门--C++类和对象总结,通过具体的内容展现,希望对大家C++的学习有一定的帮助。

本文主要是C++基础入门--C++类和对象总结,通过具体的内容展现,希望对大家C++的学习有一定的帮助。

C++基础入门--C++类和对象总结



本篇文章将会主要讲解构造函数的初始化列表,static成员,以及内部类,目的是对前几章讲解类时候的一个深入和总结.


再谈构造函数

我们上一节讲解构造函数时候,了解了构造函数的定义和使用,明白编译器会通过调用构造函数给类成员一个初始值,但是注意了~~,这个过程却并不是初始化,而是只能叫做赋初值,因为初始化只能一次,比如下面的一段代码:


class A {

public:

    A(int c = 10) {

        cout << "A(int c)" << endl;

        _c = c;

    }

private:

    int _c;

};


class B {

public:

    B(int a,int b,A& ca) {

        _a = a;

        _b = b;

        _ca = ca;

    }

private:

    int _a;

    int _b;

    A _ca;

};


int main() {

    A a(20);

    B b(1,2,a);

    return 0;

}


大家觉得上面的结果会是什么?没错,会打印两句A(int c),但是博主在这里有个小小问题,就这两句分别在哪一行代码后打印的呢?


答案:


第一次定义A对象后,会调用一次构造函数,也就打印了第一句A(int c).

第二次打印确是在程序B(int a,int b,A& ca)之后,程序_a = a之前,也就是在这两句之间,不信吗?我们下图为例:

C++基础入门--C++类和对象总结


当程序执行到_a = a以后,已经打印出了A(int c),那么这是为什么呢? 请看下一小节的初始化列表.


初始化列表

以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式


什么意思呢?如下:


class Date {

public:

    Date(int year, int month, int day) 

        :_year(year),_month(month),_day(day)

    {

    }

    void Print(){

        cout<<"year是"<<_year<<endl;

        cout<<"month是"<<_month<<endl;

        cout<<"day是"<<_day<<endl;

    }

private:

    int _year;

    int _month;

    int _day;

};


int main(){

    Date date(2021,10,23);

    date.Print();

return 0;

}

C++基础入门--C++类和对象总结



我们可以清晰地看到,通过构造函数的初始化列表,就已经成功初始化了类数据成员.所以现在大家应该已经明白了,为什么说初始化列表才是真正的初始化数据成员,而通过构造函数的函数体赋值形式叫做初次赋值.因为在函数体内部的赋值性质是可以修改初始化列表的结果,比如把构造函数改成下面这样:


    Date(int year, int month, int day) 

        :_year(year),_month(month),_day(day)

    {

            _year = 2000;

            _month = 1;

            _day = 1;

    }


那么刚才的结果将会是这样:

C++基础入门--C++类和对象总结



初始化列表注意点

①每个数据成员只能在初始化列表中出现一次(因为只能初始化一次),还是按照上面的Date类为例,若这样写就错误了:


Date(int year, int month, int day) 

    :_year(year),_month(month),_day(day),_year(2000),_month(10),_day(20)

{

}


②数据初始化顺序只和数据声明顺序有关,与初始化列表无关:


class A

{

public:

A(int a)

:_a1(a)

,_a2(_a1)

{}

void Print() {

cout<<_a1<<" "<<_a2<<endl;

}

private:

int _a2;

int _a1;

};

该类的结果为:

C++基础入门--C++类和对象总结



我们能够发现,_a2的值并不是100,因为最开始初始化的数据就是_a2,但是给_a2的值缺是还没有初始化的_a1


③当类中含有以下三种数据成员时候,对他们初始化必须使用初始化列表,分别是:


引用成员变量

const成员变量

自定义类型成员变量(没有默认的构造函数时候)

class A

{

public:

    A(int a)

    :_a(a)

    {}

private:

    int _a;

};


class B

{

public:

    B(int a, int ref)

    :_aobj(a)

    ,_ref(ref)

    ,_n(10)

    {}

private:

    A _aobj; // 没有默认构造函数

    int& _ref; // 引用

    const int _n; // const

};


explicit关键字

他的作用说简单点就是不允许定义对象时候使用=形式初始化,比如:


class Date {

public:

    explicit Date(int n) 

    {

        _n = n;

    }

private:

    int _n;

};


int main()

{

    Date date1(100);  

    Date date2 = 100; //正常情况下,这样也是可以初始化的,但是加了explict就不可以.

    return 0;

}


static成员

概念:主要有两种,一种是修饰数据成员,称为静态成员变量.一种是修饰成员函数,称为静态成员函数.其中静态成员变量必须在类外进行初始化,并且静态成员大小不计算在类内.


其特性为:


静态成员为所有类对象所共享,不属于某个具体的实例

class Date {

  public:

    Date(int b  = 10)

    {

        _a++;

        _b = b;

    }

    static void cntans()

    {

        cout<<_a<<endl;

    }

    private:

static int _a;    

    int _b;

};


int Date::_a = 10;   //静态成员必须在外面初始化.


int main()

{

    Date d1;

    Date d2;

    Date d3;

    d1.cntans();

    d2.cntans();

    d3.cntans();

    return 0;

}


大家猜猜会打印什么呢?答案如下:

C++基础入门--C++类和对象总结



可以清晰的看到,三次打印都是13,原因就是因为静态成员由所有类对象共享,并不是属于某个具体对象


类静态成员即可用类名::静态成员或者对象.静态成员来访问

在上面我们已经使用过了对象.静态成员访问格式,现在就介绍一下类名::静态成员.


仍然以上面为例:


int main(){

Date d1;

    Date::cntans();    //类名::静态成员格式

    return 0;

}


静态成员函数没有隐藏的this指针,不能访问任何非静态成员

我们仍然以上面Date类为例,比如下面的修改cntans函数的错误形式:


    static void cntans()

    {

        cout<<_a<<endl;  //_a是静态成员,类内访问没问题.

        cout<<_b<<endl; //但是_b是非静态成员,由于没有this指针,所以访问_b非法.

    }


静态成员和静态函数也有public、protected、private3种访问级别,也可以具有返回值

这个博主就不再赘述,大家自行检查.


友元

友元和静态很相似,具有两种.修饰函数的叫做友元函数,修饰类的叫做友元类.在我们介绍这个之前,先做一个小测验吧,我们利用之前学过的重载运算符,对<<或者>>进行重载,实现的类仍然是我们上面的日期类


友元函数

class Date

{

public:

    Date(int year, int month, int day)

    : _year(year)

    , _month(month)

    , _day(day)

    {}

    

    ostream& operator<<(ostream& out)

    {

    out<<_year<<"-"<<_month<<"-"<<_day;

    return cout;

    }

private:

    int _year;

    int _month;

    int _day;

};


大家觉得我们这样进行重载,会不会有什么问题呢?我们先调用一下试试吧.


Date date(2021,10,10);

cout << date;


我们进行编译,运行然后就能发现结果报错:

C++基础入门--C++类和对象总结



为什么呢?我们之前在讲运算符重载时候强调过,我们在写参数列表时,需要按照运算符的操作数格式进行重载.但是这里呢>我们按照了吗,并没有,因为这里有隐藏的this指针,也就是说操作数弄反位置了.那怎么进行修改呢?目前我们的办法只有一个,那就是放到全局:


ostream& operator<<(ostream& out,Date& date)

{

    out << _year << "-" << _month << "-" << _day;

    return cout;

}


但是像这样又会遇到一个问题,那就是_year等成员是私有的,在外部无法访问.那又怎样进行解决呢?现在就是我们的老大哥—friend友元驾临.


这种情况我们只需要在类Date中的任何位置放一份重载函数声明,并在前面加上friend.


class Date

{

    

    friend ostream& operator<<(ostream& out,Date& date);  //一般习惯性的是加在这里

    

public:

    Date(int year, int month, int day)

    : _year(year)

    , _month(month)

    , _day(day)

    {}    

private:

    int _year;

    int _month;

    int _day;

};


注意:友元函数,只需要在函数的声明前加上friend就行,并且友元不属于任何类,只是为了突破类的作用域限制,以达到访问类的私有或保护成员.


并且友元函数不可以用const进行修饰,不受任何的类作用域符限制,而同一个友元函数还可以是多个类的友元.


友元类

友元类和友元函数相似,当一个类A是类B的友元类后,类A便可以访问B的任何成员和函数.使用方法和友元函数一模一样,不再介绍.


内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限。

注意:内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元.


特性:


内部类可以定义在外部类的public、protected、private都是可以的。

注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。

sizeof(外部类)=外部类,和内部类没有任何关系

class A

{

private:

    static int k;

    int h;

public:

    class B

    {

    public:

        void foo(const A& a)

        {

            cout << k << endl;//

            cout << a.h << endl;//   //想要访问外部类的其他成员,必须通过外部类的对象参数.

        }

    };

};

int A::k = 1;


int main()

{

    A::B b;        //定义内部类,只能通过作用域限制符.

    b.foo(A());

    return 0;

}


我是小职,记得找我

✅ 解锁高薪工作

✅ 免费获取基础课程·答疑解惑·职业测评

C++基础入门--C++类和对象总结

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程