当前位置: 首页 > article >正文

C++ 基础04

对象数组

        存储对象的数组

分类

        静态对象数组        类名 数组名[长度] = {对象1,对象2,...};

        动态对象数组        类名* 数组名 = new[长度]{对象1,对象2,对象3,...};

        >注意:动态数组需要释放

        >语法为:delete [] 数组名

静态成员

概述

        使用static修饰的成员

分类

        静态成员变量

                语法:static 数据类型 变量名;

                注意:必须在类中定义,类外初始化

                        静态的成员变量属于该类的所有对象,该类的所有对象共同拥有

                        静态成员变量可以直接使用类名调用,

                        语法:类名::静态成员变量名

        静态成员函数

                语法:static 返回值类型 函数名(形参列表)

                        {

                                函数体

                        }

                注意:不能使用this关键字,则该函数中不能使用本类的非静态成员

                        可以使用类名直接调用,语法为

                        类名::静态成员函数(实参列表)

                        也可以使用对象名,函数名(实参列表)调用

单例模式

引入

        代码设计的模块之一.是一种解决问题的思路,而单例模式解决的问题是:一个类只能创建一个对象

分类

懒汉式

        1>私有化构造函数(使类外无法创建该类的对象

        2>提供公共的的静态成员函数返回该类对象(保证返回的该类对象是唯一的)

        3>在该类中定义一个静态成员该成员的数据类型就是该类,该成员变量默认为NULL

        4>在步骤2提供的函数中判断步骤3的成员变量是否为NULL,如果为空则创建该类对象,如果不为空直接返回

注意:存在线程不安全问题

饿汉式

        1>私有化构造函数(类外无法创建该类对象)

        2>提供公共化静态成员函数返回该类的对象,(保证返回该类对象的唯一性)

        3>在该类中定义一个静态成员,该成员的数据类型就是该类,该成员的变量默认为创建的该类对象

        4>在步骤2提供的函数中直接返回步骤3创建的对象

注意:线程安全,但是有些浪费内存

对象的存储

        静态成员在类加载之初被加载,不占对象的空间

        非静态成员加载在对象中

        成员函数加载到代码区

友元

作用

        A的友元函数或者友元类可以直接访问A的私有成员

关键字

        friend

注意

        友元不能继承        友元不能被继承        友元关系是单向的        友元打破类的封装性

friend修饰

        可用来修饰全局函数,成员函数,一整个类,三种,所以友元也分为三种

分类

友元全局函数

       步骤:

        1>定义一个类

        2>定义一个函数

        3>在1>类中声明2>中的函数为友元函数

                语法:friend 返回值类型 函数名(形参列表);

        4>在2>定义的函数可以访问1>类中的私有成员(即被private修饰的成员)

友元成员函数

步骤:

        声明一个类,如A        语法:class A;

        定义一个B类

        在B类中声明一个函数,该函数为A的友元函数,该函数只声明,不实现

        定义A类

        声明B类中的函数为A类的友元函数,在A类中书写       

        语法:friend 返回值类型 B::函数名(行参列表);

        实现B类声明的函数

如:

string

概述

        是一种随字符串进行操作的类,所需头文件为string

使用

        语法:string 变量名 = 值;        如:string str = "abc";        原因:隐式转换

输出

        可以通过cout之间输出,显示其中的内容        原因:重载<<运算符

赋值

        语法:string 变量名 = string 变量名;

字符串拼接

        语法:变量名1 = 变量名2 + 变量名3;        变量名1 += 变量名2;

输入

        语法:cin >> 变量名;

比较内容是否相同

        语法:变量名1 == 变量名2;

c_str

        语法:const char *变量名 = string对象名.c_str();

        作用:将c++的string类的对象转换为C语言的字符数组,需注意浅拷贝

如:

       string str07 = "hello";

        char *str08 = (char *)(str07.c_str());

        cout << "str08 = " << str08 << endl;

        str08[0] = 'T';

        cout << "str08[0] = " << str08[0] << endl;

        cout << "str07 = " << str07 << endl; cout << "str08 = " << str08 << endl;

 length

        语法:int 变量名 = string对象名.length();

        作用:测量string对象中存储的字符串长读,不包含\0;

重载运算符

概述

        是对已有的运算符进行重新定义,赋予其另一种功能,以适用不同的数据类型

关键字

        operator

语法

        返回值类型 operator运算符(即要重新定义的运算符)(形参列表)

        {

                函数体

        }

        如:>>

        void operotra >>(形参列表)

        {

        }

思路

        1、分析运算符的运算对象的个数
        2、分析运算符左边的运算对象是 自定对象 还是其他
        左边:是其他 只能全局函数实现 (必须使用友元),有几个元素参与就有几个参数,第一个

        参数是符号左边的,第二个参数是符号右边
        左边:自定义对象  
        可以用使用全局函数重载运算符(参数个数 和 运算符对象的个数一致)
        也可以使用成员函数重载运算符(参数可以少一个) (推荐)

注意

        尽量不要重载&& ||,无法实现&& || 短路

示例1:重载<<,>>运算符

题目:自定义学员类,使其可以通过cout输出其对象的成员变量的值

分析:

cout << s << endl;

第一个<<需要通过全局函数重载<<运算符,使其可以打印学生类的信息,并返回cout以便于完成第二个<<的输出

步骤:

1,定义学生类

2,使用全局函数重载<<运算符,在该函数中打印学生类对象的信息,该函数两个参数,

一个参数是cout,第二个参数是要打印的学生类对象,返回值为cout

3,将步骤2的函数声明为步骤1中定义类的全局友元函数

4,定义main函数

5,main函数中创建学生类对象

6,使用重载<<函数

代码:

#include <iostream>

#include <string>

using namespace std;

class Stu{

friend ostream& operator<<(ostream& o,Stu &s);

private:

string name;

int age;

public:

Stu(string name,int age):name(name),age(age){}

void show_info()

{

cout << name << "\t" << age << endl;

}

};

ostream& operator<<(ostream& o,Stu &s)

{

o << s.name << "\t" << s.age;

}

int main(int argc, char const *argv[])

{

Stu s1("张三",18);

Stu s2("德玛",21);

cout << s1 << endl;

return 0;

}

示例2:重载+运算符

题目:自定义学员类,创建其对其,使其可以通过+使其年龄增长

分析:s + 2

方案1:使用全局函数重载+

#include <iostream>

#include <string>

using namespace std;

class Stu{

friend void operator>>(istream& i,Stu& s);

friend void operator+(Stu& s,int age);

private:

string name;

int age;

public:

Stu(string name,int age):name(name),age(age){}

void show_info()

{

cout << name << "\t" << age << endl;

}

};

void operator>>(istream& i,Stu& s)

{

i >> s.name >> s.age;

}

void operator+(Stu& s,int age)

{

s.age = s.age + age;

}

int main()

{

Stu s("abc",18);

cin >> s;

s.show_info();

s + 3;

s.show_info();

return 0;

}

方案2:使用成员函数重载+

#include <iostream>

#include <string>

using namespace std;

class Stu{

friend void operator>>(istream& i,Stu& s);

private:

string name;

int age;

public:

Stu(string name,int age):name(name),age(age){}

void show_info()

{

cout << name << "\t" << age << endl;

}

void operator+(int age)

{

this->age += age;

}

};

void operator>>(istream& i,Stu& s)

{

i >> s.name >> s.age;

}

int main()

{

Stu s("abc",18);

cin >> s;

s.show_info();

s + 3;

s.show_info();

return 0;

}

示例3:重载==运算符

题目

判断两个对象的属性值是否相同

分析

Stu s1("张三",18);

Stu s2("张三",18);

bool b = s1 == s2;

示例4:重载++运算符

注意

++运算符分为++在前与++在后两种所以需要重载两种

当编译器看到++a(前置++),它就调用 operator++(Type& a)(全局函数),operator++ ()(成员函数)

当编译器看到a++(后置++),它就会去调用 operator++(Type& a,int)(全局函 数),operator++(int)(成员函数)

题目

++使学院年龄+1

示例5:重载*->

智能指针

代码分析问题

#include <iostream>

using namespace std;

class Data{

private:

int x,y,z;

public:

Data(){

cout << "无参构造函数" << endl;

}

Data(int a,int b,int c):x(a),y(b),z(c){

cout << "有参构造函数" << endl;

}

~Data()

{

cout << "析构函数" << endl;

}

};

int main(int argc, char *argv[])

{

Data *p = new Data();

return 0;

}

观察以上代码,我们发现创建的对象没有被销毁,但是我们在编写代码时经常会忘记销毁,那该怎么办呢?

解决方案如下

#include <iostream>

using namespace std;

class Data{

private:

int x,y,z;

public:

Data(){

cout << "无参构造函数" << endl;

}

Data(int a,int b,int c):x(a),y(b),z(c){

cout << "有参构造函数" << endl;

}

~Data()

{

cout << "析构函数" << endl;

}

};

class FreeData{

private:

Data* p;

public:

FreeData(){

p = NULL;

}

FreeData(Data* data){

p = data;

}

~FreeData(){

if(p != NULL)

{

delete p;

p = NULL;

}

}

};

int main(int argc, char *argv[])

{

FreeData fd(new Data(1,2,3));

return 0;

}

现在我们发现Data对象可以销毁,但是如何调用其对象中的属性呢?

方案如下

#include <iostream>

using namespace std;

class Data{

private:

int x,y,z;

public:

Data()

cout << "无参构造函数" << endl;

}

Data(int a,int b,int c):x(a),y(b),z(c){

cout << "有参构造函数" << endl;

}

~Data()

{

cout << "析构函数" << endl;

}

int getX()

{

return x;

}

};

class FreeData{

private:

Data* p;

public:

FreeData(){

p = NULL;

}

FreeData(Data* data){

p = data;

}

~FreeData(){

if(p != NULL)

{

delete p;

p = NULL;

}

}

Data& operator *()

{

return *p;

}

Data* operator ->()

{

return p;

}

};

int main(int argc, char *argv[])

{

FreeData fd(new Data(1,2,3));

cout << (*fd).getX() << endl;

cout << fd->getX() << endl;

return 0;

}

示例6:重载()

#include <iostream>

using namespace std;

class Data{

public:

int x,y,z;

public:

Data()

{

}

Data(int x,int y,int z):x(x),y(y),z(z){}

void operator()(int x,int y,int z)

{

this->x = x;

this->y = y;

this->z = z;

}

};

ostream& operator<<(ostream& o,Data& d)

{

o << d.x << "\t" << d.y << "\t" << d.z;

return o;

}

int main(int argc, char const *argv[])

{

Data d;

d(1,2,3);

d(4,5,6);

cout << d << endl;

return 0;

}

示例7:重载=

注意

=重载时,可能会调用类本身的拷贝构造函数。

如果左值是没有创建的对象时,会调用拷贝构造函数.

如果左值是已创建的类对象,会执行 =重载函数,实现数据的拷贝。

如:

#include <iostream>

#include <string>

using namespace std;

class Data{

public:

int x,y,z;

public:

Data()

{

}

Data(int x,int y,int z):x(x),y(y),z(z){}

Data(const Data& d)

{

cout << "拷贝构造" << endl;

}

void operator=(Data& d)

{

cout << "operator=" << endl;

this->x = d.x;

this->y = d.y;

this->z = d.z;

}

};

int main(int argc, char const *argv[])

{

// string str01 = "hello";

// string str02 = str01; //拷贝构造

// string str03 = "world";

// str03 = str01;

Data d1 = Data(1,2,3);

Data d2;

d2 = d1;

cout << d2.x << d2.y << d2.z << endl;

return 0;

}


http://www.kler.cn/a/414158.html

相关文章:

  • 51c大模型~合集79
  • 软路由设置ip地址实现一机一IP
  • C++自动化测试:GTest 与 GitLab CI/CD 的完美融合
  • spring boot框架漏洞复现
  • PointNet++论文复现
  • 【Git】常用命令汇总
  • 深入解析 Canny 边缘检测:原理、步骤与实践应用全攻略
  • Redis的基础知识·
  • java虚拟机——jvm是怎么去找垃圾对象的
  • word emailing + vba拆分word文件并转pdf
  • json转sql建表语句
  • Proteus 8.17的详细安装教程
  • IDEA报错: java: JPS incremental annotation processing is disabled 解决
  • 【电力行业标准】《电力信息化软件工程度量规范》(DL/T 2015-2019)-费用标准解读系列20
  • Python 散列类型:数据索引与处理的智慧密钥
  • 深度学习Pytorch中的模型保存与加载方法
  • Web Worker 入门:让前端应用多线程化
  • JS异步进化与Promise
  • 六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序
  • scala的守卫语句格式
  • Vue.js 中的事件监听与事件修饰符
  • git flow 相关知识 git rebase 与 merge 合并差异比较
  • TortoiseSVN 基本操作 - 下载/上传/更新/repo查看
  • PAT甲级-1064 Complete Binary Search Tree
  • 记录一次在生产环境中更换 SSL 证书的操作
  • Qt creator设置程序图标