知识点13【explicit关键字】
c++提供了关键字explicit,禁止通过构造函数进行隐式转换。声明为explicit的构造函数不能在隐式转换中使用。
#include <iostream>
using namespace std;
class Data
{
private:
int num;
public:
Data()
{
cout<<"Data无参构造"<<endl;
}
explicit Data(int a):num(a)
{
cout<<"Data有参构造"<<endl;
}
~Data()
{
cout<<"Data析构函数"<<endl;
}
};
int main(int argc, char *argv[])
{
Data data = 10;
Data data1(15);
Data data2 = Data(20);
cout << "Hello World!" << endl;
return 0;
}
运行结果:
知识点14【new和delete】从堆区申请空间
1、和malloc 、calloc、realloc比较
(1)malloc返回一个void指针,c++不允许将void赋值给其他任何指针,必须强转。 (2)malloc可能申请内存失败,所以必须判断返回值来确保内存分配成功。 (3)maloc不会调用构造函数,free不会调用析构函数(重要的)
2、new给基本类型申请空间
void test01(){
int* a = new int;
*a = 100;
cout<<"*a = "<<*a<<endl;
delete a;
}
new申请基本类型空间
void test02(){
int *a = new int[5];
int *b = new int[5]{1,2,3,4,5};
for(int i = 0; i < 5; i++){
cout << a[i] << " ";
}
cout << endl;
delete [] a;
for(int i = 0; i < 5; i++){
cout << b[i] << " ";
}
cout << endl;
delete [] b;
char *arr = new char[15];
strcpy(arr,"hehe");
cout << arr << endl;
delete [] arr;
}
运行结果: 注意:(1)new没有加[],delete释放的时候就不加[]. (2)new加[],delete释放的时候就加[].
3、new和delete给类对象申请空间
void test03(){
Data *data = new Data();
delete data;
}
运行结果:
class Data
{
private:
int num;
char *str;
public:
Data()
{
cout<<"Data无参构造"<<endl;
}
Data(int a,char *str1):num(a),str(str1)
{
cout<<"Data有参构造"<<endl;
}
~Data()
{
cout<<"Data析构函数"<<endl;
}
void showData(){
cout << num << " " << str << endl;
}
};
void test04(){
Data *data = new Data(100,"hehe");
data->showData();
delete data;
}
运行结果:
知识点15【对象数组】
本质还是数组,只是数组的每个元素是类的对象
void test05(){
char *data = "hehehehe";
int arr[3];
Data arr1[5];
}
运行结果:
2、如果让对象数组中的元素调用有参构造,必须人为使用有参构造初始化
void test06(){
Data arr2[5] = {Data(50,"haha"),Data(60,"xixi")};
arr2[0].showData();
arr2[1].showData();
}
运行结果:
3、用new和delete申请对象数组
void test07(){
Data *arr1 = new Data[5];
delete [] arr1;
Data *arr2 = new Data[5]{Data(50,"haha"),Data(60,"xixi")};
(*arr2).showData();
arr2[0].showData();
(arr2+1)->showData();
delete [] arr1;
}
运行结果:
4、尽量不要用delete释放void*
注意:没有析构 ,这是因为data1指向的类型未void,无法从void中寻找响应析构函数
5、malloc、free、和new 、delete不能混搭使用
知识点15【静态成员】static修饰的成员
成员:成员变量、成员函数 static修饰成员变量和成员函数 static声明为静态的,称为静态成员。不管这个类创建了多少对象,静态成员只有一个拷贝,这个拷贝被所有属于这个类的对象共享。 静态成员属于类,而不是对象。
1、static修饰成员变量
静态变量,是在编译阶段就分配空间,对象还没有创建时,就已经分配空间 静态变量必须在类内声明,类外定义(普通成员变量可以类内定义)。 静态数据成员不属于某个对象,在为对象分配空间中不包括静态成员所占的空间。
class Data2{
public:
int num;
static int data;
};
int Data2::data = 100;
void test(){
cout << Data2::data << endl;
Data2::data = 200;
cout << Data2::data << endl;
Data2 *ob1 = new Data2();
ob1->data = 300;
cout << Data2::data << endl;
Data2 *ob2 = new Data2();
cout << ob2->data << endl;
ob1->num = 100;
cout << ob2->num << endl;
}
2、static修饰静态成员函数
class Data2{
private:
int num;
static int data;
public:
static int getData(){
return data;
}
};
int Data2::data = 100;
void test10(){
cout << Data2::getData()<<endl;
Data2 *ob1 = new Data2();
cout << ob-> getData() << endl;;
}
注意:1、静态成员函数的目的是操作静态成员数据 2、静态成员函数不能访问非静态成员数据。(静态成员函数内部没有this指针) 3、普通成员函数可以操作静态成员数据和非静态成员数据
class Data2{
private:
int num;
static int data;
public:
int getNum(){
num = 100;
return data;
}
static int getData(){
return data;
}
};
4、静态成员变量和静态成员函数都有权限之分
3、const修饰静态成员
如果一个类的成员,既要实现共享,又要实现不可改变,那就用static const修饰
知识点16【静态成员案例】
案例一:静态成员统计类实例化对象的个数
#include <iostream>
using namespace std;
class Data
{
public:
static int count;
public:
Data()
{
cout<<"Data无参构造"<<endl;
count++;
}
Data(const &ob){
cout<<"Data拷贝构造"<<endl;
count++;
}
~Data()
{
cout<<"Data析构函数"<<endl;
count--;
}
};
int Data::count = 0;
int main(int argc, char *argv[])
{
Data ob1;
Data ob2;
{
Data ob3;
Data ob4;
cout << "对象个数:" << Data::count << endl;
}
cout << "对象个数:" << Data::count << endl;
return 0;
}
运行结果: 案例2:单例模式–打印机(重要) 步骤1:在单例类内部定义了一个Singletion类型的静态对象,作为外部共享的唯一实例。 步骤i2:提供一个公共静态的方法,让客户可以访问他的唯一实例。 步骤3:为了防止外部实例化其他对象,将其默认构造函数和拷贝构造函数设为私有。
class Printer{
private:
static Printer *SignlePrint;
Printer(){
count = 0;
}
Printer(const Printer &ob){}
public:
static Printer* getSignLePrint(){
return SignlePrint;
}
void printText(char* str){
cout << "打印" << str << endl;
count++;
}
int count;
};
Printer *Printer::SignlePrint = new Printer();
int main(int argc, char *argv[])
{
Printer *p1 = Printer::getSignLePrint();
p1->printText("入职报告1");
p1->printText("体检报告1");
p1->printText("离职报告1");
Printer *p2 = Printer::getSignLePrint();
p2->printText("入职报告2");
p2->printText("体检报告2");
p2->printText("离职报告2");
cout << p2->count << endl;
return 0;
}
知识点17【this指针的引入】(重要)
c++的封装性:将数据和方法封装在一起,但数据和方法是分开存储的,每个对象拥有独立的数据,但方法是公用一份的。
1、this指针的引入
class Data2{
public:
int m_num;
void setNum(int num){
m_num = num;
}
};
int main(int argc, char *argv[])
{
Data2 ob1 = Data2();
ob1.setNum(10);
cout << "ob1.m_num = " << ob1.m_num << endl;
Data2 ob2 = Data2();
ob2.setNum(20);
cout << "ob2.m_num = " << ob2.m_num << endl;
Data2 ob3 = Data2();
ob3.setNum(30);
cout << "ob3.m_num = " << ob3.m_num << endl;
return 0;
}
运行结果: 分析: 上面的代码可以修改为:
class Data2{
public:
int m_num;
void setNum(int num){
this->m_num = num;
}
};
int main(int argc, char *argv[])
{
Data2 ob1 = Data2();
ob1.setNum(10);
cout << "ob1.m_num = " << ob1.m_num << endl;
Data2 ob2 = Data2();
ob2.setNum(20);
cout << "ob2.m_num = " << ob2.m_num << endl;
Data2 ob3 = Data2();
ob3.setNum(30);
cout << "ob3.m_num = " << ob3.m_num << endl;
return 0;
}
注意:
- this指针是隐含在对象成员函数内的一种指针
- 成员函数通过this指针即可知道操作的是哪个对象的数据
- 静态成员函数内部没有this指针,因此静态成员函数不能操作非静态成员变量(静态成员函数是属于类,函数内部没有this指针)
c++编译器对普通成员函数的内部处理:
知识点18【this指针的使用】
1、当形参名和成员变量名同名时,可用this指针来区分
class Data2{
public:
int num;
void setNum(int num){
this->num = num;
}
};
2、在类的普通成员函数中返回对象本身(*this)(重要)
class MyCout{
public:
MyCout& myCout(char *str){
cout << str;
return *this;
}
};
int main(int argc, char *argv[])
{
MyCout ob = MyCout();
ob.myCout("hehehe").myCout("hahaha").myCout("xixixi");
}
运行结果:
|