类中的一些特殊情况
学习目的
掌握类中的特殊成员(变量 & 函数)
掌握友元关系(**)
掌握单例模式
1. this指针
this 指针是系统自动生成,且隐藏的;
this 不是对象的一部分,作用域在类的内部;
类的普通函数访问类的普通成员时,this 指针总是指向所调用的对象。
普通数据成员,每个对象都有单独的一份,成员函数整个类都只有一份,多个对象共用。
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
public:
void setNum(int n);
int getNum();
private:
int num;
};
void MyClass::setNum(int num)
{
// 如何在类的成员函数里面区分 自己的数据成员 以及同名的参数?
// 使用 this 指针!
num = num;
}
int MyClass::getNum()
{
return num;
}
int main()
{
MyClass obj_0;
obj_0.setNum(10);
cout << "num = " << obj_0.getNum() << endl;
return 0;
}
this指针:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
public:
void setNum(int n);
int getNum();
private:
int num;
};
void MyClass::setNum(int num)
{
// 如何在类的成员函数里面区分 自己的数据成员 以及同名的参数?
// 使用 this 指针!
this->num = num;
}
int MyClass::getNum()
{
return num;
}
int main()
{
MyClass obj_0;
obj_0.setNum(10);
cout << "num = " << obj_0.getNum() << endl;
return 0;
}
如果成员函数的参数与成员变量参数不重名,则不需要使用this指针,
否则必须使用this指针。
2. static成员(**)
在C++类中声明成员时,加上 static 关键字;
静态成员分为静态数据成员和静态函数成员。
静态成员可直接通过类名访问。
静态数据成员
给静态数据成员初始化时需在类外进行,不能再构造函数中初始化。
#include <iostream>
#include <string>
using namespace std;
class ClassName
{
public:
ClassName();
~ClassName();
static int num;
};
int ClassName::num = 0;
ClassName::ClassName()
{
}
ClassName::~ClassName()
{
}
int main()
{
//ClassName obj_0;
//cout << "num = " << obj_0.num << endl;
return 0;
}
特点:
-
类中所有对象全部共享着同一段静态数据成员的内存(图中篮框);
验证:
#include <iostream>
#include <string>
using namespace std;
class ClassName
{
public:
ClassName();
~ClassName();
static int num;
};
int ClassName::num = 0;
ClassName::ClassName()
{
}
ClassName::~ClassName()
{
}
int main()
{
ClassName obj_0;
cout << "obj_0.num = " << obj_0.num << endl;
obj_0.num = 5;
ClassName obj_1;
cout << "obj_1.num = " << obj_1.num << endl;
return 0;
}
静态数据成员在类创建之前就已经有了,生命周期比类长(比任何一个对象都长),属于整个类不属于任何一个对象,因此可以通过类名+作用域符访问
ClassName::num;
静态成员函数
静态成员函数不能访问普通数据成员(非静态变量),也无法调用普通成员函数,也无法使用this指针。
用例:
#include <iostream>
#include <string>
using namespace std;
class ClassName
{
public:
ClassName();
~ClassName();
static int num;
static void testFunc_1();
static void testFunc_2()
{
cout << " ClassName::testFunc_2()" << endl;
}
};
int ClassName::num = 0;
void ClassName::testFunc_1()
{
cout << " ClassName::testFunc_1()" << endl;
}
ClassName::ClassName()
{
num++;
}
ClassName::~ClassName()
{
}
int main()
{
ClassName obj_0;
cout << "obj_0.num = " << obj_0.num << endl;
//obj_0.num = 5;
ClassName obj_1;
cout << "obj_1.num = " << obj_1.num << endl;
// 对象成员访问
obj_1.testFunc_1();
// 指针访问
ClassName* p = &obj_0;
p->testFunc_2();
// 类名访问
ClassName::testFunc_1();
ClassName::testFunc_2();
return 0;
}
单例模式:设计模式(解决一类问题的通用方法)
创建一个只能实例化一个对象的类(但是可以多个指针指向它)
单例举例:
#include <iostream>
using namespace std;
// 单例模式:创建一个只能实例一个对象的类
// 从构造函数的角度上限制
class SingleInstance
{
public:
~SingleInstance();
static SingleInstance* getInstance();
private:
SingleInstance();
SingleInstance(const SingleInstance& obj);
static SingleInstance* pInstance;
public:
int num;
};
SingleInstance* SingleInstance::pInstance = NULL;
SingleInstance::SingleInstance()
{
num = 0;
}
SingleInstance::SingleInstance(const SingleInstance& obj)
{
}
SingleInstance* SingleInstance::getInstance()
{
if (pInstance == NULL)
{
pInstance = new SingleInstance;
}
return pInstance;
}
SingleInstance::~SingleInstance()
{
}
int main()
{
SingleInstance* p1 = SingleInstance::getInstance();
cout << "num = " << p1->num << endl;
SingleInstance* p2 = SingleInstance::getInstance();
p2->num = 99;
SingleInstance* p3 = SingleInstance::getInstance();
cout << "num = " << p3->num << endl;
cout << hex << p1 << endl;
cout << hex << p2 << endl;
cout << hex << p3 << endl;
return 0;
}
3. const 成员
在C++类中声明对象时加上 const 关键字,常量成员分为常量数据成员和常量函数成员。
常量数据成员
#include <iostream>
using namespace std;
class ClassName
{
public:
ClassName();
ClassName(int v);
ClassName(int v,int num);
~ClassName();
int num;
const int val;
};
ClassName::ClassName() : val(0)
{
num = 0;
}
ClassName::ClassName(int v) : val(v)
{
num = v;
}
// 使用成员初始化列表对非静态成员初始化
ClassName::ClassName(int v, int num) : val(v), num(num)
{
}
ClassName::~ClassName()
{
}
int main()
{
ClassName obj_1;
cout << "obj_1.val = " << obj_1.val << endl;
ClassName obj_2;
cout << "obj_2.val = " << obj_2.val << endl;
ClassName obj_3(6);
cout << "obj_3.val = " << obj_3.val << endl;
ClassName obj_4(7, 8);
cout << "obj_3.val = " << obj_3.val << endl;
cout << "obj_4.val = " << obj_4.val << " " << "obj_4.num = " << obj_4.num << endl;
return 0;
}
常量成员函数
类外实现常量成员函数时,const 关键字不能丢掉(const 属于成员函数的一部分,定义和实现都需要加在()后面。)
#include <iostream>
using namespace std;
class ClassName
{
public:
ClassName();
ClassName(int v);
ClassName(int v,int num);
~ClassName();
int num;
const int val;
void testFunc_1();
// 常成员函数声明
void testFunc_2() const;
};
ClassName::ClassName() : val(0)
{
num = 0;
}
ClassName::ClassName(int v) : val(v)
{
this->num = v;
}
// 使用成员初始化列表对非静态成员初始化
ClassName::ClassName(int v, int num) : val(v), num(num)
{
}
// 普通成员函数定义
void ClassName::testFunc_1()
{
cout << "test_Func_1()" << endl;
cout << "val = " << this->val << endl;
cout << "num = " << this->num << endl;
}
// 常成员函数定义
void ClassName::testFunc_2() const
{
cout << "test_Func_2()" << endl;
cout << "val = " << this->val << endl;
cout << "num = " << this->num << endl;
}
ClassName::~ClassName()
{
}
int main()
{
ClassName obj_1;
cout << "obj_1.val = " << obj_1.val << endl;
ClassName obj_2;
cout << "obj_2.val = " << obj_2.val << endl;
ClassName obj_3(6);
cout << "obj_3.val = " << obj_3.val << endl;
ClassName obj_4(9, 8);
obj_4.testFunc_1();
obj_4.testFunc_2();
return 0;
}
const 成员函数的意义:常量成员函数不能对类里面的任何数据成员进行修改(只能访问,不能修改。)但是,可以修改静态数据成员。
常对象
常对象只能调用常成员函数(也不能修改常成员变量) 或静态成员。
#include <iostream>
using namespace std;
class ClassName
{
public:
ClassName();
ClassName(int v);
ClassName(int v,int num);
~ClassName();
int num;
const int val;
void testFunc_1();
// 常成员函数声明
void testFunc_2() const;
static int n;
};
int ClassName::n = 0;
ClassName::ClassName() : val(0)
{
num = 0;
}
ClassName::ClassName(int v) : val(v)
{
this->num = v;
}
// 使用成员初始化列表对非静态成员初始化
ClassName::ClassName(int v, int num) : val(v), num(num)
{
}
// 普通成员函数定义
void ClassName::testFunc_1()
{
cout << "test_Func_1()" << endl;
cout << "val = " << this->val << endl;
cout << "num = " << this->num << endl;
}
// 常成员函数定义
void ClassName::testFunc_2() const
{
cout << "test_Func_2()" << endl;
cout << "val = " << this->val << endl;
cout << "num = " << this->num << endl;
}
ClassName::~ClassName()
{
}
int main()
{
ClassName obj_1;
cout << "obj_1.val = " << obj_1.val << endl;
ClassName obj_2;
cout << "obj_2.val = " << obj_2.val << endl;
ClassName obj_3(6);
cout << "obj_3.val = " << obj_3.val << endl;
ClassName obj_4(9, 8);
obj_4.testFunc_1();
obj_4.testFunc_2();
const ClassName obj_5(3, 4);
// obj_5.num = 2; // 常对象不能修改普通成员变量,可以修改静态成员变量(静态成员变量不属于单独的某一个对象)
obj_5.n = 7;
// obj_5.test_func_1(); // 常对象也不能调用普通成员函数(普通成员函数有修改数据成员的权限)。
obj_5.testFunc_2(); // 常对象只能调用常成员函数 或 静态成员。
ClassName const obj_6(3,4);
//obj_6.num = 2;
obj_6.n = 9;
return 0;
}
4. 友元关系:friend(**)
类的特性之一是封装(private),友元是打破封装的手段。
友元分为友元函数和友元类;
友元类可以创建友元对象。
友元函数
#include <iostream>
using namespace std;
class A
{
int num;
friend void testFunc_1(A obj);
public:
A()
{
this->num = 1;
}
};
void testFunc_1(A obj)
{
obj.num = 0;
}
int main()
{
A a;
testFunc_1(a);
return 0;
}
友元类
#include <iostream>
using namespace std;
class A
{
int num;
friend class B;
};
class B
{
public:
void testFunc(A obj)
{
obj.num;
}
};
int main()
{
return 0;
}
特点:单方向、不具有传递性、不继承。
<未完待续>