一、对象初始化列表
类中如果有一个其他类的对象,而其他类没有无参构造函数,无法初始化
该类的对象,需要对象初始化列表对其进行初始化
注意点:
1、对象初始化列表的优先级高于当前对象的构造函数进行
2、对象的构造和在对象初始化列表中的位置无关,和在类中声明的顺序有关
3、const常量必须在初始化列表中初始化
下面举个圆与点的列子:
class Point
{
public:
Point(int x, int y)
{
m_x = x;
m_y = y;
printf ("Point 构造函数:%d, %d\n", m_x, m_y);
}
~Point()
{
printf ("Point 析构函数:%d, %d\n", m_x, m_y);
}
void print()
{
printf ("x = %d, y = %d\n", m_x, m_y);
}
private:
int m_x;
int m_y;
};
class Circle
{
public:
Circle(int r, int x, int y): c1(4,5), c(x, y), m_r(r), a(r)
{
// m_r = r;
printf ("Circle 构造函数\n");
}
~Circle()
{
printf ("Circle 析构函数\n");
}
void print()
{
printf ("r = %d\n", m_r);
c.print();
}
private:
int m_r;
Point c1;
Point c;
const int a; // const 常量
};
构造函数中不要调用其他构造函数,无法完成初始化操作
二、对象的动态创建和释放
1、在C语言中使用的是malloc和free实现在堆上空间的分配和释放
在C++中使用的是new和delete实现在堆上空间的分配和释放
2、区别:
malloc和free是库函数,是C语言标准库提供的函数,不是C语言的一部分
new和delete是C++运算符,C++语法的一部分,new和delete效率比malloc和free高
基础数据类型空间分配
// C++ new delete
// new : new 数据类型
int *p2 = new int; // 分配一个整型空间
*p2 = 12;
cout << *p2 << endl;
delete p2; // 释放空间
// new 的时候可以直接初始化
// new 数据类型(初始值)
、int *p3 = new int(5);
cout << *p3 << endl;
delete p3;
动态分配数组
void func5_2()
{
// C: 分配数组 int a[100];
int *p = (int *)malloc(sizeof(int)/sizeof(char)*100);
// 释放
free(p);
// C++:
// new : new 数据类型[个数]
// new 分配数组的时候是不能进行初始化的
int *p1 = new int[100];
// 释放数组:delete []
// 不加 [] 会造成内存泄露
delete [] p1;
}
动态分配对象
void func5_3()
{
// C语言仅仅是在堆上 分配了 一个对象的空间
Test5_1 *p1 = (Test5_1*)malloc(sizeof(Test5_1)/sizeof(char));
free (p1);
// C++
// new 对象的时候 会调用对象的构造函数对对象进行初始化
Test5_1 *p2 = new Test5_1;
// delete 的时候 会调用对象的析构函数 回收对象的资源
delete p2;
Test5_1 *p3 = new Test5_1(10); // 有参构造
delete p3;
}
三、类中的静态成员
1、静态成员函数只能使用静态成员变量
2、静态成员变量是类的成员,不是对象的成员,属于类,所有类的对象所共享的参数
3、静态成员变量必须重新定义并初始化
静态成员变量使用方式
1、通过对象使用
2、通过类名::去使用
t2.m_sa = 300;
cout << "Test6_1::m_sa = " << Test6_1::m_sa << endl;
Test6_1::m_sa = 89;
cout << "t2.m_sa = " << t2.m_sa << endl;
class Test7_1
{
public:
Test7_1(int a, int b)
{
m_a = a;
m_b = b;
}
// 类的普通成员函数内都有一个隐藏的指针 this, 该指针指向当前操作的对象
void print () // ===> void print (Test7_1 *const this)
{
printf ("a = %d, b = %d\n", this->m_a, this->m_b);
}
// 静态成员函数内部没有 this 指针,所以无法使用类的普通成员变量
static void printA ()
{
printf ("m_sa = %d\n", m_sa);
}
private:
int m_a;
int m_b;
static int m_sa;
};
int Test7_1::m_sa = 10;
class Test7_2
{
public:
Test7_2(int a, int b)
{
this->a = a;
this->b = b;
}
void print () const // void print (const Test7_1 *const this) //函数()后的const表示,隐式指向的对象不可修改
{
printf ("a = %d, b = %d\n", this->a, this->b);
}
public:
int a;
int b;
};
// 类的内部成员函数和全局函数 实现同样的功能 有哪些不一样的地方
// 全局函数比 类的内部函数 多了一个参数
void print(Test7_2 &obj) // Test7_2 * const this
{
printf ("a = %d, b = %d\n", obj.a, obj.b);
}
int main7_2()
{
Test7_2 t(1,2);
t.print();
return 0;
}
五、友元函数和友元类
要在类的外部使用类中的私有成员,使用友元函数,让全局函数操作类的私有成员变量
友元函数的声明:在函数原型前加上关键字friend
注意点:
1、友元函数不是类的成员函数,是一个全局函数‘
2、友元函数的声明可以放在类的任意位置,public,private,protected对friend声明无效
3、友元函数破坏了类的封装性,一般不建议试用
4、友元函数没有 this 指针,因为它是全局函数而不在类的内部
5、如果A类是B类的友元类,则A类的所有成员函数都是B类的友元函数