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;

}

相关推荐
geovindu19 分钟前
python: generator model using mysql9.0 or postgreSQL 17.0
开发语言·python·mysql·postgresql
萨达大26 分钟前
23种设计模式-单例(Singleton)设计模式
java·c++·单例模式·设计模式·软考·创建型设计模式·软件设计师
oscar99927 分钟前
Java 语言的起源发展与基本概念(JDK,JRE,JVM)
java·开发语言·jvm
ll92311630 分钟前
C++和C中的volatile 关键字
c语言·c++
Pandaconda35 分钟前
【新人系列】Python 入门(十四):文件操作
开发语言·笔记·后端·python·面试·操作系统·测试
go_bai36 分钟前
动态内存管理的知识点笔记总结
c语言·开发语言·笔记·c#·学习方法
zaim136 分钟前
计算机的错误计算(一百六十八)
java·c++·python·matlab·rust·c#·大数
Reeeeeeeeeee-38 分钟前
[MRCTF2020]Transform
c语言·开发语言·汇编·c++·算法
萨达大42 分钟前
23种设计模式-装饰器(Decorator)设计模式
java·c++·设计模式·软考·装饰器模式·软件设计师·结构型设计模式
Koishi_TvT1 小时前
蓝桥杯c++算法秒杀【6】之动态规划【上】(数字三角形、砝码称重(背包问题)、括号序列、组合数问题:::非常典型的必刷例题!!!)
c++·学习·算法·蓝桥杯·深度优先·动态规划·c