一、始化列表
当⼀个类对象作为另⼀个类的对象成员时,有时会出现⼀些初始化上的问题
1. const成员变量初始化
2. 引⽤成员变量初始化
3. ⽆默认构造函数对象成员初始化
4. 其他普通场景也可以使⽤初始化列表
class Sword{
public:
Sword(int attack, int crit){
m_attack = attack;
m_crit = crit;
}
private:
int m_attack; // 基础攻击⼒
int m_crit; // 暴击伤害
};
class Hero{
public:
Sword m_sword;
};
void test()
{
Hero hero;
}
创建 hero对象时,m_sword必须要能够构造,默认编译器会调⽤ Sord类的默认构造函数,当Sword提供了有参构造时,编译器默认的成员对象的构造⾏为就会失效,这就需要使⽤初始化列表来解决该问题,通过初始化列表指定对象成员调⽤那个构造函数完成初始化。
class Hero{
public:
// 新增代码
Hero() : m_sword(10, 20) {}
Hero(int v1, int v2) : m_sword(v1, v2) {}
// 新增结束
public:
Sword m_sword;
};
如果类中包含多个对象成员,编译器会按照对象成员定义顺序逐个调⽤构造函数。
初始化列表也可以⽤于基本数据类型的成员:
class Person
{
public:
Person(int a, int b, int c) : m_a(a), m_b(b), m_c(c) {}
private:
int m_a;
int m_b;
int m_c;
};
** 二、动态对象
1. 对象必须包含默认构造,编译器默认调⽤⽆参构造来完成对象初始化。
2. delete void * 不会调⽤析构函数。
new运算符创建对象时,⾸先调⽤ malloc分配内存空间,然后调⽤对应的构造函数。
delete运算符销毁对象时,⾸先调⽤对象析构函数,然后调用free函数释放内存。
class Person{
public:
Person(){
m_score = 0;
m_age = 0;
}
Person(int score, int age){
m_score = score;
m_age = age;
}
void print(){
cout << m_score << " " << m_age << endl;
}
private:
int m_score;
int m_age;
};
void test()
{
// 1. 创建单个对象
Person *person1 = new Person;
Person *person2 = new Person(10, 20);
delete person1;
delete person2;
// 2. 创建对象数组
Person *person3 = new Person[2];
delete[] person3;
}
三、静态成员
C++类中的成员只有两种:
1. ⾮静态成员,归属对象所有。通过对象访问。
2. 静态成员,归属本类型所有对象共享。通过对象或者类访问。
静态成员分为:静态成员函数、静态成员变量。
1.静态成员变量
1. 静态成员变量在定义时必须在类中声明,在类外定义。
2. 静态成员变量也具有访问控制权限。
class StaticMemberVariable
{
public:
static int s_public_num;
private:
static int s_private_num;
};
// 静态成员变量类内定义类外初始化
int StaticMemberVariable::s_public_num = 100;
int StaticMemberVariable::s_private_num = 200;
void test()
{
// 1. 通过类名来访问
cout << StaticMemberVariable::s_public_num << endl;
// 2. 通过对象来访问
StaticMemberVariable smv;
cout << smv.s_public_num << endl;
// 3. 私有静态成员变量不能访问
//cout << StaticMemberVariable::s_private_num << endl;
//cout << smv.s_private_num << endl;
}
2.const修饰的静态成员变量
如果成员变量,既要共享,⼜不可改变,可以⽤ static const修饰。定义静态 const数据成员时,最好
在类内部初始化
class StaticMemberFunction
{
public:
//const static int s_num;
// 2. 类内初始化
const static int s_num = 100;
};
// 1. 类外初始化
//const int StaticMemberFunction::s_num = 100;
void test()
{
cout << StaticMemberFunction::s_num << endl;
// StaticMemberFunction::s_num = 200;
}
3 静态成员函数
1. 静态成员函数只能只能访问静态成员变量。
2. 静态成员变量、静态成员函数同样具有访问权限。
3. ⾮静态成员函数既可以访问静态成员变量、⾮静态成员变量。
class StaticMemberFunction
{
public:
static void public_print()
{
cout << "public_print" << endl;
// 静态成员函数只能访问静态成员变量
cout << StaticMemberFunction::s_variable << endl;
// cout << StaticMemberFunction::m_variable << endl;
}
// 普通成员函数可以访问静态成员变量、⾮静态成员变量
void print()
{
cout << m_variable << endl;
cout << s_variable << endl;
}
private:
static void private_print()
{
cout << "private_print" << endl;
}
public:
int m_variable;
static int s_variable;
};
int StaticMemberFunction::s_variable = 100;
void test()
{
// 1. 通过类名来访问
StaticMemberFunction::public_print();
// 2. 通过对象来访问
StaticMemberFunction smf;
smf.public_print();
// 3. 私有静态成员函数不能访问
// StaticMemberFunction::private_print();
// smf.private_print();
}
四、this指针
为什么一个函数在内存中只有一份函数实例,但是有两个对象调用时,如何区分到底是哪个对象调用的函数
为什么静态成员函数只能只能访问静态成员变量
这两个问题的解答全在this指针
1. this 是⼀个常量指针,⽆法修改指向。
2. 当对象创建完成之后,编译器会创建并初始化⼀个 this 指针,该指针指向创建的对象。
3. this 指针并不存储在对象内部,⽽是会放置在所有的⾮静态成员函数的第⼀个参数,这是隐含
操作,由编译器完成。
4. 当⾮静态成员函数内部使⽤成员变量时,编译器会通过 this 指针来访问该变量。
5. 编译器不会为静态成员函数传递 this 指针,静态成员函数⽆法访问⾮静态成员变量。
1. 当形参和成员变量同名时,可⽤ this 指针来区分
2. 在类的⾮静态成员函数中返回对象本身,可使⽤ return this
class CppObjectModel
{
public:
CppObjectModel(int num){
this->num = num;
}
CppObjectModel &get_object(){
return *this;
}
public:
int num;
};
五、const成员函数
1. const成员函数指的是函数不能通过 this指针修改成员变量的值。
2. mutable修饰的成员变量不受 const函数限制。
3. const对象只能调⽤ const修饰的成员函数。
class CppObjectModel
{
public:
CppObjectModel(){
this->num = 100;
this->mutable_num = 200;
}
void get_object() const{
// this->num = 200; // 禁⽌修改
this->mutable_num = 300; // 允许修改
}
void print(){
cout << "num:" << num << " mutable_num" << mutable_num << endl;
}
public:
int num;
mutable int mutable_num;
};
void test()
{
// 1. ⾮ const 对象可以调⽤任何函数
CppObjectModel com1;
com1.get_object();
com1.print();
// 2. const 对象只能调⽤ const 成员函数
const CppObjectModel com2;
com2.get_object();
// com2.print(); // 禁⽌调⽤⾮const成员函数
}