创作过程中难免有不足,若您发现本文内容有误,恳请不吝赐教。
提示:以下是本篇文章正文内容,下面案例可供参考。
一、static成员
概念:声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。
问题:
实现一个类,计算程序中创建出了多少个类对象。
#include<iostream>
using namespace std;
// 累积创建了多少个对象
int n = 0;
// 正在使用的还有多少个对象
int m = 0;
class A
{
public:
A()
{
++n;
++m;
}
A(const A& t)
{
++n;
++m;
}
~A()
{
--m;
}
};
A Func(A aa)
{
return aa;
}
int main()
{
A aa1;
A aa2;
cout << n << " " << m << endl;
A();
cout << n << " " << m << endl;
Func(aa1);
//aa1传给aa要拷贝构造一次,return传值返回也要拷贝一次
cout << n << " " << m << endl;
return 0;
}
//引用返回
A& Func(A aa)
{
return aa;
}
//引用传参
A& Func(A& aa)
{
return aa;
}
可以看出,引用传参和引用传返回很有意义。如果返回,尽量去用引用返回,出了作用域对象还在。
缺陷:可以被外面随意修改m 、n的值
#include<iostream>
using namespace std;
class A
{
public:
A()
{
++n;
++m;
}
A(const A& t)
{
++n;
++m;
}
~A()
{
--m;
}
//private:
// 静态成员变量属于所有A对象,属于整个类,存储在静态区
//声明
static int n;
static int m;
};
// 定义
int A::n = 0;
int A::m = 0;
A Func(A aa)
{
return aa;
}
int main()
{
A aa1;
A aa2;
cout << A:: n << " " << A::m << endl;
A();
cout << aa1.n << " " << aa1.m << endl;
Func(aa1);
cout << aa2.n << " " << aa2.m << endl;
return 0;
}
上面的方式仅限于m、n是公有。
//用一个成员函数获取
void Print()
{
cout << m <<" " << n << endl;
}
int main()
{
//但这种情况无法调用Print()
A();
A();
}
#include<iostream>
using namespace std;
class A
{
public:
A()
{
++n;
++m;
}
A(const A& t)
{
++n;
++m;
}
~A()
{
--m;
}
static void Print()
{
// 静态成员函数的特点:没有this指针
// x++; // 不能访问非静态,因为没有this
cout << m <<" " << n << endl;
}
//private:
// 静态成员变量属于所有A对象,属于整个类,存储在静态区
//声明
static int n;
static int m;
int x = 0;
};
// 定义
int A::n = 0;
int A::m = 0;
A Func(A aa)
{
return aa;
}
int main()
{
A();
A();
//直接用类名访问
A::Print();
A aa1;
Func(aa1);
aa1.Print();
return 0;
}
二、内部类
概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
#include<iostream>
using namespace std;
//B类受A类域和访问限定符的限制,其实他们是两个独立的类
class A
{
public:
class B
{
private:
int _b;
};
private:
int _a;
};
int main()
{
cout << sizeof(A) << endl;
return 0;
}
可以定义A对象,但不能定义B对象。
int main()
{
A aa;
//得指定类域
A::B bb;
return 0;
}
class A
{
//public:
//定义成私有外面也是用不了
class B
{
private:
int _b;
};
private:
int _a;
};
注意:内部类就是外部类的友元类
,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
三、动态内存管理
C语言内存管理方式在
C++
中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++
又提出了自己的内存管理方式:
通过
new
和
delete
操作符进行动态内存管理。
#include<iostream>
using namespace std;
int main()
{
int* p1 = (int*)malloc(sizeof(int));
// 动态申请一个int类型的空间
int* p2 = new int;
//多个对象
int* p3 = (int*)malloc(sizeof(int)*10);
int* p4 = new int[10];
free(p1);
free(p3);
delete p2;
delete[] p4;
return 0;
}
注意:申请和释放单个元素的空间,使用new
和
delete
操作符,申请和释放连续的空间,使用
new[]
和
delete[]
,注意:匹配起来使用。
#include<iostream>
using namespace std;
int main()
{
// 额外支持开空间+初始化
int* p1 = new int(10);
int* p2 = new int[10] {1, 2, 3};
return 0;
}
#include<iostream>
using namespace std;
class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
int main()
{
// malloc没有办法很好支持动态申请的自定义对象初始化
A* p1 = (A*)malloc(sizeof(A));
//p1->_a = 0;
//p1->A(1);
// 自定义类型,开空间+调用构造函数初始化
A* p2 = new A;
A* p3 = new A(3);
// 自定义类型,调用析构函数+释放空间
delete p2;
delete p3;
//多个对象
A* p4 = new A[10];
delete[] p4;
A aa1(1);
A aa2(2);
A* p5 = new A[10]{ aa1, aa2 };
delete[] p5;
A* p6 = new A[10]{ A(3), A(4) };
delete[] p6;
A* p7 = new A[10]{ 5, 6 };
delete[] p7;
return 0;
}
注意:在申请自定义类型的空间时,
new
会调用构造函数,
delete
会调用析构函数,而
malloc
与
free
不会
。
简单的列表实现:
#include<iostream>
using namespace std;
struct ListNode
{
ListNode* _next;
int val;
ListNode(int val = 0)
:val(0)
,_next(nullptr)
{}
};
int main()
{
ListNode* n1 = new ListNode(1);
ListNode* n2 = new ListNode(2);
ListNode* n3 = new ListNode(3);
ListNode* n4 = new ListNode(4);
ListNode* n5 = new ListNode(5);
n1->_next = n2;
n2->_next = n3;
n3->_next = n4;
n4->_next = n5;
return 0;
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了c++的基础知识。