千家信息网

C++的对象特性和友元是什么

发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,这篇文章主要介绍了C++的对象特性和友元是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++的对象特性和友元是什么文章都会有所收获,下面我们一起来看看吧。对象特征构
千家信息网最后更新 2025年02月01日C++的对象特性和友元是什么

这篇文章主要介绍了C++的对象特性和友元是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++的对象特性和友元是什么文章都会有所收获,下面我们一起来看看吧。

    对象特征

    构造函数和析构函数

    对象的初始化和清理也是两个非常重要的安全问题

    一个对象或者变量没有初始状态,对其使用后果也是未知

    同样的使用完一个对象或变量,没有及时清理,也会造成一定的安全问题

    • 构造函数:主要作用在于创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用

    • 析构函数:主要作用在于对象销毁前系统自动调用,执行一些清理工作

    构造函数语法:类名(){}

    1.构造函数,没有返回值也不写void

    2.函数名称与类名相同

    3.构造函数可以有参数,因此可以发生重载

    4.程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次

    析构函数语法:~类名(){}

    1.析构函数,没有返回值也不写void

    2.函数名称与类名相同,在名称前加上符号~

    3.析构函数不可以有参数,因此不可以发生重载

    4.程序在调用对象前会自动调用析构,无须手动调用,而且只会调用一次

    #includeusing namespace std;//对象的初始化和清理//1.构造函数  实现初始化的操作class Person {public:        //1构造函数        //没有返回值  不用写void        //函数名 与类名相同        //构造函数可以有参数,可以发生重载        //创建对象时,构造函数会自动调用,而且只调用一次        Person() {                cout<< "Person构造函数的调用" << endl;        }        //2.析构函数  实现清理的操作        //没有返回值 不写void         //函数名和类名相同 在名称前加一个~        //析构函数不可以有参数,不可以发生重载        //对象在销毁前 会自动调用析构函数 而且只会调用一次        ~Person() {                cout << "Person析构函数的调用" << endl;        }};//构造和析构都是必须有的实现,如果我们自己不提供,编译器会提供一个空实现的构造和析构void test01() {        Person p;//在栈上的数据,test01执行完毕后,释放这个对象} int main() {        test01();        system("pause");        return 0;}

    函数的分类以及调用

    构造函数的分类以及调用

    两种分类方式:

    • 按参数分为:有参构造和无参构造

    • 按类型分:普通构造和拷贝构造

    三种调用方式:

    • 括号法

    • 显示法

    • 隐式转换法

    #includeusing namespace std;//构造函数的分类及调用//分类//按照参数分类  无参构造(默认构造)和有参构造//按照类型分类  普通构造 拷贝构造class Person {public:        //构造函数        Person() {           cout << "Person的无参构造函数调用" << endl;        }        Person(int a) {                age = a;                cout << "Person的有参构造函数调用" << endl;        }        //拷贝构造函数        Person(const Person &p) {                //将传入的人身上的所有属性,拷贝到"我"身上                age = p.age;                cout << "Person的拷贝构造函数调用" << endl;        }        ~Person() {                cout << "Person的析构函数调用" << endl;        }        int age;};//调用void test01() {        //1.括号法        //Person p1;//默认函数调用        //Person p2(10);//有参构造函数        //Person p3(p2);//拷贝构造函数        //注意事项        //调用默认构造函数的时候,不要加()        //因为下面这行代码,编译器会认为是一个函数的声明,不会认为在创建对象        //Person p1();      /*cout << "p2的年龄:" << p2.age << endl;        cout << "p3的年龄:" << p3.age << endl;*/        //2.显示法        //Person p1;        //Person p2 = Person(10);//有参构造        //Person p3 = Person(p3);//拷贝构造        //Person(10);//匿名对象 特点:当前行执行结束后,系统会立即回收掉匿名对象        //        // 注意事项2        // 不要利用拷贝构造函数,初始化匿名对象  编译器会认为Person(p3) === Person p3;对象声明        //Person(p3);   //3.隐式转换法        Person p4 = 10;//相当于 写了 Person p4 = Person(10); 有参构造        Person p5 = p4;//拷贝构造}int main() {        test01();        system("pause");        return 0;}

    拷贝构造函数调用时机

    拷贝构造函数调用时机通常有三种情况

    1.使用一个已经创建完毕的对象来初始化一个新对象

    2.值传递的方式给函数参数传值

    3.以值方式返回局部对象

    #includeusing namespace std;//拷贝构造函数的调用时机//1.使用一个已经创建完毕的对象来初始化一个新对象//2.值传递的方式给函数参数传值//3.值方式返回局部对象class Person {public:        Person() {                cout << "Person的默认构造函数调用" << endl;        }        Person(int age) {                cout << "Person的有参构造函数调用" << endl;                m_Age = age;        }        Person(const Person &p) {                cout << "Person的拷贝构造函数调用" << endl;                m_Age = p.m_Age;        }        ~Person() {           cout << "Person析构函数调用" << endl;        }        int m_Age;};//拷贝构造函数的调用时机//1.使用一个已经创建完毕的对象来初始化一个新对象void test01() {        Person p1(20);        Person p2(p1);        cout << "p2的年龄为:" << p2.m_Age << endl;}//2.值传递的方式给函数参数传值void doWork(Person p) {  } void test02() {        Person p;        doWork(p);} //3.值方式返回局部对象Person doWork2() {        Person p1;        return p1;}void test03() {        Person p = doWork2();}int main() {          //test01();        //test02();        test03();        system("pause");        return 0;}

    构造函数调用规则

    默认情况下,c++编译器至少给一个类添加3个函数

    1.默认构造函数(无参,函数体为空)

    2.默认析构函数(无参,函数体为空)

    3.默认拷贝构造函数,对属性进行值拷贝

    构造函数调用规则如下

    如果用户定义有参构造函数,c++不再提供默认无参构造,但是会提供默认拷贝构造

    如果用户定义拷贝构造函数,c++不再提供其他构造函数

    #includeusing namespace std;//构造函数的调用规则//1.创建了一个类,c++编译器会给每个类都添加至少三个函数//默认构造  (空实现)//析构函数  (空实现)//拷贝构造  (值拷贝)//2.如果我们写了有参构造函数,编译器就不再提供默认构造,依然提供拷贝构造//如果我们写了拷贝构造函数,编译器不再提供其他构造函数了class Person {public:        /*Person() {                cout << "Person的默认构造函数调用" << endl;        }*/        /*Person(int age) {                cout << "Person的有参构造函数调用" << endl;                m_Age = age;        }*/        Person(const Person& p) {                cout << "Person的拷贝构造函数调用" << endl;                m_Age = p.m_Age;}   ~Person() {                cout << "Person的析构函数调用" << endl;        }        int m_Age;};//void test01() {//      Person p;//      p.m_Age = 18;//      Person p2(p);//      cout << "p2的年龄为:" << p2.m_Age << endl;//}void test02() {        Person p(28);        Person p2(p);        cout << "p2的年龄为:" << p2.m_Age << endl;}int main() {        //test01();        test02();        system("pause");        return 0;}

    深拷贝与浅拷贝

    • 浅拷贝:简单的赋值拷贝操作

    • 深拷贝:在堆区重新申请空间,进行拷贝操作

    #includeusing namespace std;//深拷贝与浅拷贝class Person {public:        Person() {                cout << "Person的默认构造函数调用" << endl;        }        Person(int age,int height) {                m_Age = age;                m_Height = new int(height);                cout << "Person的有参构造函数调用" << endl;        }        Person(const Person &p) {                cout << "Person 拷贝构造函数的调用" << endl;                m_Age = p.m_Age;                //m_Height = p.m_Height; 编译器默认实现就是这行代码                //深拷贝操作                //如果不利于深拷贝在堆区创建内存,会导致浅拷贝带来的重复释放堆区问题                m_Height = new int(*p.m_Height);        }        ~Person() {                //析构堆区,将堆区开辟数据做释放操作                if (m_Height != NULL) {                        delete m_Height;                        m_Height = NULL;                        //浅拷贝带来的问题就是堆区的问题重复释放                        //浅拷贝的问题 要利用深拷贝进行解决                }                cout << "Person的析构函数调用" << endl;        }        int m_Age;//年龄        int* m_Height;//身高};void test01() {        Person p1(18,160);        cout << "p1的年龄为:" << p1.m_Age <<"身高为:"<<*p1.m_Height << endl;        Person p2(p1);        cout << "p2的年龄为:" << p2.m_Age <<"身高为:"<<*p2.m_Height << endl;}int main() {        test01();        system("pause");        return 0;}

    如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题

    初始化列表

    作用:c++提供了初始化列表语法,用来初始化属性

    语法:构造函数():属性1(值1),属性2(值2)...{}

    #includeusing namespace std;//初始化列表class Person {public:        //传统初始化操作        /*Person(int a, int b, int c) {                m_A = a;                m_B = b;                m_C = c;        }*/        //初始化列表初始化属性        Person(int a,int b,int c) :m_A(a), m_B(b), m_C(c) {   }        int m_A;        int m_B;        int m_C;};void test01() {        //Person p(10, 20, 30);        Person p(30,20,10);        cout << "m_A = " << p.m_A << endl;        cout << "m_B = " << p.m_B << endl;        cout << "m_C = " << p.m_C << endl;  }int main() {        test01();        system("pause");        return 0;}

    类对象作为类变量

    c++类中的成员可以是另一个类的对象,我们称该成员为 对象成员

    例如:

    class A{}

    class B

    {

    A a;

    }

    B类中有对象A作为成员去,A为对象成员

    #includeusing namespace std;//类对象作为类成员//手机类class Phone {public:        Phone(string pName) {                cout << "Phone的构造函数调用" << endl;                m_PName = pName;        }        ~Phone() {                cout << "Phone的析构函数调用" << endl;        }        //手机品牌名称        string m_PName; };//人类class Person {public:        //Phone m_Phone = pName  隐式转换法        Person(string name, string pName):m_Name(name),m_Phone(pName)        {                cout << "Person的构造函数调用" << endl;        }        ~Person() {                cout << "Person的析构函数调用" << endl;        }        //姓名        string m_Name;        //手机        Phone m_Phone;};//当其他类对象作为本类成员,构造时先构造类对象,再构造自身,析构的顺序与构造相反void test01() {        Person p("张三","苹果");        cout << p.m_Name << "拿着" << p.m_Phone.m_PName << endl; }int main() {        test01();        system("pause");        return 0;}

    静态成员

    静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员

    静态成员分为:

    静态成员变量

    所有对象共享一份数据

    在编译阶段分配内存

    类内声明,类外初始化

    静态成员函数

    所有对象共享同一个函数

    静态成员函数只能访问静态成员变量

    #includeusing namespace std;//静态成员函数//所有对象共享同一个函数//静态成员函数只能访问静态成员变量class Person {public:        //静态成员函数        static void func() {                m_A = 100;//静态成员函数可以访问静态成员变量                //m_B = 200;//静态成员函数不可以访问非静态成员变量,无法区分到底是哪个m_B                cout << "static void func的调用" << endl;        }        static int m_A;//静态成员变量        int m_B;//非静态成员变量        //静态成员函数也是有访问权限的private:        static void func2() {                cout << "static void func2的调用" << endl;        }};int Person::m_A = 0;//有两种访问方式void test01() {        //1.通过对象进行访问        Person p;        p.func();        //2.通过类名访问        Person::func();        //Person::func2();类外访问不到私有的静态成员函数}int main() {        test01();        system("pause");        return 0;}

    成员变量和成员函数分开储存

    在c++中,类的成员变量和成员函数分开存储

    只有非静态成员变量才属于类的对象上

    #includeusing namespace std;//成员变量和成员函数是分开存储的class Person {        int m_A;//非静态成员变量  属于类的对象上的        static int m_B;//静态成员变量  不属于类的对象上        void func() {}//非静态成员函数  不属于类的对象上        static void func2() {}//静态成员函数  不属于类的对象上};int Person::m_B = 0;void test01() {        Person p;        //空对象占用的内存空间为:1        //c++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置        //每个空对象也应该有一个独一无二的内存地址        cout << "size of p = "<

    this指针的用途

    • this指针指向被调用的成员函数所属的对象

    • this指针是隐含每一个非静态成员函数内的一种指针

    • this指针不需要定义,直接使用即可

    this指针的用途:

    当形参和成员变量同名时,可用this指针来区分

    在类的非静态成员函数中返回对象本身,可使用return * this返回

    #includeusing namespace std;class Person {public:        Person(int age) {                //this指针指向被调用的成员函数所属的对象                this->age = age;        }        int age;        Person PersonAddAge(Person &p) {                this->age += p.age;                //this指向p2的指针,而*this指向的就是p2这个对象本体                return *this;        }}; //1.解决名称冲突void test01() {        Person p1(18);        cout << "p1的年龄为:" << p1.age << endl;}//2.返回对象本身用*thisvoid test02() {        Person p1(10);        Person p2(10);        //链式编程思想        p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);        cout << "p2的年龄为:" << p2.age << endl;} int main() {        //test01();        test02();        system("pause");        return 0;}

    空指针访问成员

    c++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针

    如果用到this指针,需要加以判断保证代码的健壮性

    #includeusing namespace std;//空指针调用成员函数class Person {public:   void showClassName() {                cout << "this is Person class" << endl;        }        void showPersonAge() {                //报错原因是因为传入的指针是为NULL                if (this == NULL)                {                        return;                }                cout << "age = " < m_Age << endl;        }        int m_Age;};void test01() {        Person* p = NULL;        //p->showClassName();        p->showPersonAge();}int main() {        test01();   system("pause");        return 0;}

    const修饰成员函数

    常函数

    成员函数后加const后我们称这个函数为常函数

    函数内不可以修改成员属性

    成员属性声明时加关键字mutable后,在常函数中依然可以修改

    常对象:

    声明对象前加const称该对象为常对象

    常对象只能调用常函数

    #includeusing namespace std;//空指针调用成员函数class Person {public:   void showClassName() {                cout << "this is Person class" << endl;        }        void showPersonAge() {                //报错原因是因为传入的指针是为NULL                if (this == NULL)                {                        return;                }                cout << "age = " < m_Age << endl;        }        int m_Age;};void test01() {        Person* p = NULL;        //p->showClassName();        p->showPersonAge();}int main() {        test01();   system("pause");        return 0;}

    友元

    友元的目的就是让一个函数或者类访问另一个类中私有成员

    友元关键字为friend

    友元的三种实现:

    • 全局函数做友元

    • 类做友元

    • 成员函数做友元

    全局函数做友元

    #includeusing namespace std;#include//建筑物类class Building {        //goodGay全局函数是Building好朋友,可以访问Building中私有成员        friend void goodGay(Building* building);public:        Building() {                m_SittingRoom = "客厅";                m_BedRoom = "卧室";        }public:        string m_SittingRoom;//客厅private:        string m_BedRoom;//卧室};//全局函数void goodGay(Building *building) {        cout << "好基友全局函数 正在访问:" << building->m_SittingRoom << endl;        cout << "好基友全局函数 正在访问:"<m_BedRoom << endl;}void test01() {        Building building;        goodGay(&building);}int main() {        test01();        system("pause");        return 0;}

    类做友元

    #includeusing namespace std;#include//类做友元class Building;class GoodGay {public:        GoodGay();        void visit();//参观函数 访问Building中的属性        Building* building;};class Building {        //GoodGay类是本来的好朋友,可以访问本类中私有成员        friend class GoodGay;public:        Building();public:        string m_SittiingRoom;//客厅private:        string m_BedRoom;//卧室};//类外写成员函数Building::Building() {        m_SittiingRoom = "客厅";        m_BedRoom = "卧室";}GoodGay::GoodGay() {        //创建建筑物对象        building = new Building;}void GoodGay::visit() {        cout << "好基友类正在访问:"<m_SittiingRoom << endl;        cout << "好基友类正在访问:" << building->m_BedRoom << endl;}void test01() {        GoodGay gg;        gg.visit();}int main() {        test01();        system("pause");        return 0;}

    成员函数做友元

    #includeusing namespace std;#includeclass Building;class GoodGay {public:        GoodGay();        void visit();//让visit函数可以访问Building中的私有成员        void visit2();//让visit函数不可以访问Building中的私有成员        Building* building;};class Building {        //告诉编译器 GoodGay类下的visit成员函数作为本类的好朋友,可以访问私有成员        friend void GoodGay:: visit();public:        Building();public:        string m_SittingRoom;//客厅private:        string m_BedRoom;//卧室 };//类外实现成员函数Building::Building() {        m_SittingRoom = "客厅";        m_BedRoom = "卧室";}GoodGay::GoodGay() {        building = new Building;}void GoodGay::visit() {        cout << "visit函数正在访问"<m_SittingRoom << endl;        cout << "visit函数正在访问" << building->m_BedRoom << endl;}void GoodGay::visit2() {        cout << "visit2函数正在访问" << building->m_SittingRoom << endl;        //cout << "visit2函数正在访问" << building->m_BedRoom << endl;}void test01() {        GoodGay gg;        gg.visit();        gg.visit2();}int main() {        test01();   system("pause");        return 0;}

    关于"C++的对象特性和友元是什么"这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对"C++的对象特性和友元是什么"知识都有一定的了解,大家如果还想学习更多知识,欢迎关注行业资讯频道。

    0