目录
一、const成员
1.const数据成员
(1).const类型变量是不可修改的(只读模式).
(2).必须采用初始化参数列表的方式进行初始化.
class Person
{
public:
Person(string name,int age) :age(age)
{
Person::name = name; //可以这样赋值,也可以用初始化参数列表方法
//Person::age = age; --->报错,const修饰的参数只能用初始化参数列表方式进行初始化
}
protected:
string name;
const int age;
};
2.const成员函数
(1).写法上,const要加在函数后面
(2).常成员函数不能修改数据成员(只读数据成员)
void print()const//常成员函数
{
//name = "修改"; --->报错,常成员函数中不能修改数据
//age = 19; -->常成员数据也不能修改
cout << "常成员函数" << endl;
}
(3).常成员函数可以与普通函数同时存在
void print()//普通函数
{
//age = 1001; --->错误 只读模式 不能修改
cout << name << " " << age << endl;
}
void print()const//常成员函数
{
//name = "修改"; --->报错,常成员函数中不能修改数据
//age = 19; -->常成员数据也不能修改
cout << "常成员函数" << endl;
}
注: ● 普通函数和常成员函数相同时,普通对象优先调用普通函数
● 普通对象可以调用常成员函数
3.const对象
(1).定义:const修饰的对象
(2).常对象只能调用常成员函数
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(string name,int age) :age(age)
{
Person::name = name; //可以这样赋值,也可以用初始化参数列表方法
//Person::age = age; --->报错,const修饰的参数只能用初始化参数列表方式进行初始化
}
void print()//普通函数
{
//age = 1001; --->错误 只读模式 不能修改
cout << name << " " << age << endl;
}
void print()const//常成员函数
{
//name = "修改"; --->报错,常成员函数中不能修改数据
//age = 19; -->常成员数据也不能修改
cout << "常成员函数" << endl;
}
void printData()
{
cout << "普通函数" << endl;
}
protected:
string name;
const int age;
};
int main()
{
Person MM("Miss Du", 19);
MM.print();//普通对象优先调用普通函数
//两者都有时只能调用普通函数,无法强行调用常成员函数
//若只有常成员函数也可以调用常成员函数
const Person GG("Mr Y", 19);
GG.print();//输出常成员函数 常对象调用常成员函数
//GG.printData();---->常对象只能调用常成员函数
while (1);
return 0;
}
二、static成员
注:● static成员不属于对象,是属于类的,这意味着static成员是属于所有对象的(共有的),调用时可以不用对象(也可以通过对象访问).
● static成员依旧受权限限定.
1.static数据成员
(1).必须在类外初始化,初始化时不再需要static修饰,但是需要类名限定.
(2).类中初始化是错误的,不能采用初始化参数列表方式初始化.
class Person
{
public:
//Person(int age):age(age){}
//-->age不是类的非静态数据成员或者基类,因此在类内初始化或者用初始化参数列表初始化都不可以
protected:
string name;
static int age;
};
//类外初始化,不再需要static修饰,但是需要类名限定
int Person::age = 1;
2.static成员函数
(1).样式:static写在函数前面即可
(2).调用非静态成员时必须要指定对象.
class Person
{
public:
//Person(int age):age(age){}
//---->age不是类的非静态数据成员或者基类,因此在类内初始化或者用初始化参数列表初始化都不可以
Person(string name) :name(name)
{
age++;
}
static void printMM();//类外实现--->静态函数
static void printData(Person& MM)//类内声明,类内实现,可以通过对象的引用访问name数据成员
{
cout << MM.name << '\t' << age << endl;
}
protected:
string name;
public:
static int age;
};
//类外初始化,不再需要static修饰
void Person::printMM()
{
//调用非静态数据成员,必须要指定对象
//cout << name << endl; --->当这个函数不采用对象去调用,name没有来源,报错
Person MM("Miss DU");
cout << MM.name << endl;
//静态数据成员可直接调用,也可以通过对象调用
cout << age << endl;
cout << MM.age << endl;
cout << "静态成员函数" << endl;
}
3.static对象
注:释放是最后释放的
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
//Person(int age):age(age){}
//---->age不是类的非静态数据成员或者基类,因此在类内初始化或者用初始化参数列表初始化都不可以
Person(string name="") :name(name)
{
age++;
}
static void printMM();//类外实现
static void printData(Person& MM)//类内声明,类内实现,可以通过对象的引用访问name数据成员
{
cout << MM.name << '\t' << age << endl;
}
protected:
string name;
public:
static int age;
};
//类外初始化,不再需要static修饰,但是需要类名限定
int Person::age = 18;
//类外初始化,不再需要static修饰
void Person::printMM()
{
//调用非静态数据成员,必须要指定对象
//cout << name << endl; --->当这个函数不采用对象去调用,name没有来源,报错
Person MM("Miss DU");
cout << MM.name << endl;
//静态数据成员可直接调用,也可以通过对象调用
cout << age << endl;
cout << MM.age << endl;
cout << "静态成员函数" << endl;
}
int main()
{
//静态数据成员访问可以不用对象调用
cout << Person::age << endl;
//静态数据成员可以通过对象去访问
Person MM("Miss Du");
cout << MM.age << endl; //age=20
//静态数据成员是共有的
Person GG[3]; //age=23;
Person* pMM = new Person("newMM"); //age=24
cout << Person::age << endl; //age=24
cout << pMM->age << endl; //age=24
cout << MM.age << endl; //age=24
delete pMM;
pMM = nullptr;
cout << endl;
//静态成员函数
Person::printMM();
MM.printMM(); //---->三者等价
Person::printData(MM);
while (1);
return 0;
}
三、友元
1.友元的定义
● friend描述的关系.友元只是提供一个场所,赋予对象具有打破类的权限定(无视权限).
● 可以理解为朋友的是自己的,自己的也是自己的.(自我理解,或许有误)
2.友元函数
(1).普通友元函数
#include<iostream>
#include<string>
using namespace std;
void printData();//声明
class Person
{
public:
Person(string name, int age) :name(name), age(age){}
void print()
{
cout << name << '\t' << age << endl;
}
friend void printData()
{
//不属于类,不能直接访问成员 ---> 对非静态成员"Person::name"的非法引用
//cout << name << '\t' << age << < endl;
//友元函数提供一个场所,让对象无视权限
Person GG("Mr Y", 19);
cout << GG.name << '\t' << GG.age << endl;
}
protected:
string name;
private:
int age;
friend void printData2(Person& MM);//类内声明
};
//类外实现友元函数--->//不需friend修饰,不需要类名限定
void printData2(Person& MM)
{
cout << MM.name << '\t' << MM.age << endl;
}
//void printData()
//{
// //不属于类,不能直接访问成员 ---> 对非静态成员"Person::name"的非法引用
// //cout << name << '\t' << age << < endl;
// //友元函数提供一个场所,让对象无视权限
// Person GG("Mr Y", 19);
// cout << GG.name << '\t' << GG.age << endl;
//}
int main()
{
Person MM("Miss Du", 19);
MM.print();
printData(); //直接调用友元函数
printData2(MM);
while (1);
return 0;
}
(2).若以另一个类的成员函数充当友元函数,顺序如下:
● B类--->A类--->A类的友元函数(B类的成员函数)
class B
{
public:
void printA();
void printData();
protected:
};
class A
{
public:
friend void B::printA();
protected:
string name = "A";
};
//成员函数实现,一定是在另一个类的下面实现
void B::printA()
{
A a;
cout << a.name << endl;
}
void B::printData()
{
A a;
错误 ,不是他的A类的友元函数,所以不能访问保护和私有属性
//cout << a.name << endl;
}
3.友元类
注:一个类是另一个类的友元类
#include <iostream>
#include<string>
using namespace std;
class Person
{
friend class MM;
public:
Person(string name, int age) :name(name), age(age){}
protected:
string name;
int age;
};
class MM
{
public:
void print()
{
Person mm("Miss Du", 19);
cout << mm.name << "\t" << mm.age << endl;
}
void printMM(Person& mm)
{
cout << mm.name << "\t" << mm.age << endl;
}
Person& printmm(Person& mm)
{
return mm;
}
protected:
};
int main()
{
Person mm("Miss Du", 19);
MM mm2;
mm2.print();
//mm2.printMM(mm);
//cout<<(mm2.printmm(mm)).name<<endl; --->错误,出了友元类,没有权限
while (1);
return 0;
}
4.互为友元类(增加)
#include <iostream>
#include<string>
using namespace std;
//互为友元类
class Person
{
friend class MM;
public:
Person() = default;
Person(string name, int age) :name(name), age(age){}
//void printData()//无法在此处写打印MM的数据,因为会显示MM没有定义
//{
// MM mm("Miss Du", 19);
// cout << mm.name << "\t" << mm.age << endl;
//}
void printData();//可以通过类内定义,类外实现
protected:
string name;
int age;
};
class MM
{
friend class Person;
public:
MM(string name, int age) :name(name), age(age){}
void printData()
{
Person gg("Mr Y", 19);
cout << gg.name << "\t" << gg.age << endl;
}
protected:
string name;
int age;
};
void Person::printData()
{
MM mm("Miss Du", 19);
cout << mm.name << "\t" << mm.age << endl;
}
int main()
{
Person mm1;
mm1.printData();
MM mm2("Miss Du", 19);
mm2.printData();
while (1);
return 0;
}
四、this指针与explicit
1.explicit作用
● 修饰构造函数使用,不让隐式转换构造
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
explicit Person(int age) :age(age){}
explicit Person(string name, int age) :name(name), age(age){}
void print()
{
cout << name << "\t" << age << endl;
}
protected:
string name;
int age;
};
class MM
{
public:
MM(string name) :name(name){}
MM(string name, int age) :name(name), age(age){}
void print()
{
cout << name << "\t" << age << endl;
}
protected:
string name;
int age;
};
int main()
{
//explicit 不让隐式转换构造
//Person mm3 = 12;--->不存在从“int”转换为“Person”的适当构造函数
Person mm1(19); //可以如此初始化
MM mm = "Miss Du"; //可以如此初始化
while (1);
return 0;
}
2.this指针
● 避免形参名和数据成员同名,通指对象的地址
● 充当函数返回值,返回对象自身,用*this表示对象本身
● 静态成员函数中是不能使用this指针
#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
MM(string name) :name(name){}
MM(string name, int age) :name(name), age(age){}
void initData(string name, int age)
{
//普通函数不存在初始化参数列表方法--->使用this指针
this->name = name;
//类名限定 帮助计算机去识别
MM::age = age;
}
void print()
{
cout << this->name << "\t" <<this->age << endl;
}
void printThis()
{
cout << this << endl;
}
MM returnMM()
{
return *this;
}
static void printMM3()
{
//cout << this->name << endl;--->this只能用于非静态成员函数内部
MM mm("Miss Du", 20);
cout << mm.name << "\t" << mm.age << endl;
}
protected:
string name;
int age;
};
int main()
{
MM mm("Miss Du",19);
mm.print();
mm.initData("Mr Y", 20);
mm.print();
cout << &mm << endl;
mm.printThis();//this为对象的地址
MM mm2("dmw", 19);
cout << &mm2 << endl;
mm2.printThis();
MM::printMM3();
while (1);
return 0;
}