const:
①数据成员:必须用初始化成员列表初始化。
wbm(string name,const int age):name(name),age(age){}
②常成员函数:1.const在最后面
2.不可以借此作为接口来修改数据成员,也就是只读模式
3.可以和普通函数同时且同名存在,遵循“名当户对”的原则,普->普,若是在没有普通函数,则 调用常函数。
class wbm { public: wbm(string name,const int age):name(name),age(age){} void print()const { cout << "i'm an ordinary hanshu" << endl; } void print() { cout << "i'm a normal hanshu" << endl; } protected: const int age; string name; private: }; int main() { wbm gzj("王二狗", 12); gzj.print(); const wbm jiejie("wbm", 21); jiejie.print(); return 0; }
③常对象:仅能调用常函数
static成员:
前置声明:
1.属于类的而非某个对象的,也就是 共有 。 调用可以不用某个对象来调用。
(共有的这个性质,我们将会在下面初始化成员列表中 用某个数据成员++ 来验证)
2.但仍然会受到权限的限定。(在直接通过 类名限定加上::访问就会体现的很明显)
①static数据成员:
必须类外初始化,在类外的时候只需要类型+类名限定(即无需static修饰)。那么在类中或者用初始化成员列表中初始化就是不被允许的。
class wbm { public: protected: static int age; string name; }; int wbm::age = 100;
展示一下通过类来调用:
共用的具体体现:
class wbm { public: wbm(const string name=" ") :name(name) { age++;//这样写表示,每构造一个函数都会让静态age自增一次 } static int age; protected: const string name; }; int wbm::age = 1; int main() { cout << wbm::age << endl;//1 wbm k1("k1");//2 cout << wbm::age << endl; wbm k2("k2");//3 cout << wbm::age << endl; wbm k[3];//6 cout << wbm::age << endl; wbm* k3 = new wbm;//7 cout << wbm::age << endl; return 0; }
注意若加上了default默认函数,通过默认构造的函数age不会++(第二条路)
故我们通常在初始化列表里加上初始化,方便用。
其次,若想实现age++不能再初始化成员列表里加上int age;否则最终age始终停留在初始化的age值,不会在变(亲测)。
只要对静态数据成员的值更新一次,就可以保证所有对象都会存取更新后的值!!
②成员函数:
1.static放在函数名前面,类外实现无需static修饰。当然在类中实现也是可以的。
2.若调用了非静态数据成员,必须指定对象(解决:传一个对象参数进来)
解决代码实现:
//类中定义这么写 static void printdata(const wbm& mm) { cout <<mm.name<< endl; } //main中使用这么用 wbm k1("k1"); wbm::printdata(k1);
3.若调用的是静态数据:无要求。
static void printstatic_data() { cout << age << endl; }
③static对象:
最后释放!!!
友元Friend :
①定义:提供一个场所,赋予对象具有打破类的权限限定(无视权限)
(当然,仍然是通过对方的对象访问数据)
②友元函数:(不属于类,不能直接访问成员,若在类外实现,不需要friend修饰,不需要类名限定)(也不可以用对象来,访问友元函数)
1.放在函数名前
2.实现方式一:若传入了参数,是可以在类里面实现的,然后在main里面直接使用。
//类中: friend void print_no_static(const pig&mm) { cout << mm.age << "\t" << mm.name << endl; } main中: pig jie ("jie", 18); print_no_static(jie);
实际上传入参数,在类外实现也是可以的
(在类中相当于声明一下。)
实现方式二:若不传入参数,且在类中实现,main中是无法直接用的,需要前置声明函数。
前置声明:
void print_no_static(); class pig { public: pig(string name, int age) :name(name), age(age){} friend void print_no_static() { cout << height << endl; } friend void print_static(); protected: int age; string name; private: static int height; }; int pig::height = 100; //void print_no_static(const pig &mm) //{ // cout << mm.age << "\t" << mm.name << endl; //} void print_static() { cout << pig::height << endl; } int main() { pig jie ("jie", 18); print_no_static(); return 0; }
③以另一个类的成员函数充当友元函数:
顺序 :
B类
A类:friend
A类友元(即B成员函数)的实现
目的:该函数需要访问另外一个类的私有或者保护成员,比对其进行一些操作。现实生活中的一个例子就是:老师类需要对学生的成绩进行修改。
#include<iostream> using namespace std; class student; class teacher { public: void change_student_grade(student &wbm); }; class student { public: student(int grade):grade(grade){} friend void teacher::change_student_grade(student &wbm); void printGrade() { cout << "成绩"<<grade << endl; } protected: int grade; private: }; void teacher::change_student_grade(student &wbm) { wbm.grade = 100; } int main() { student wbm(99); wbm.printGrade(); teacher gzj; gzj.change_student_grade(wbm); wbm.printGrade(); return 0; }
④友元类:
1.a,b类:在A类中告诉我有friend b类,那么b类中一个函数中创建a类对象A(也可以现在函数中创建对象,也可以传引用),则a对象所有属性均可访问
目的:使用单个声明使Y类的所有函数成为类X的友元,它提供一种类之间合作的一种方式,使类Y的对象可以具有类X和类Y的功能。
#include<iostream> using namespace std; class student; class teacher { public: void print(student& mm); }; class student { public: friend teacher; student(string name, int age) :name(name), age(age) { } protected: string name; int age; }; void teacher::print(student &mm) { cout << "name=" << mm.name << endl; cout << "age=" << mm.age << endl; } int main() { teacher jie; student wbm("wbm", 18); jie.print(wbm); return 0; }
注:除了友元类就不再拥有权限了,(下面在main中用cout一个返回引用对象函数证明)
class student { public: friend class teacher; student(string name, int age) :name(name), age(age) {} protected: string name; int age; }; class teacher { public: void print(student& mm) { cout << mm.name << "\t" << mm.age << endl; } student& returnstudent(student& mm) { return mm; } }; int main() { student wbm("wbm", 18); teacher jie; jie.print(wbm); //jie.returnstudent(wbm).name << endl; //错误,一旦出了友元类,就就不再拥有权限 return 0; }
补充:互为友元类的写法
(在单向的基础上,加上类外实现的方法)
class student { public: friend class teacher; student(string name) :name(name){} void printT(); protected: string name; int age; }; class teacher { public: friend class student; teacher(string name) :name(name) { } void printS() { student wbm("wbm"); cout << wbm.name << endl; } protected: string name; }; void student::printT() { teacher jie("jie"); cout << jie.name << endl; } int main() { student mm("mm"); mm.printT(); teacher gg("jie"); gg.printS(); return 0; }
explicit:
针对于构造函数的隐式类型转换问题(不给他转),也就是不给用B b={ }来初始化。
只允许显式: B b();
this指针:
this指针”指向了成员函数作用的对象
①避免形参名和数据成员同名,通指对象的地址
②充当函数返回值,返回对象自身,用*this表示对象本身(套娃)
③静态成员函数中是不能使用this指针(类外无this)
以下来通过写一个接口initdata来展示this的用法(不用初始化成员列表的时候,不太好分区分,this可以。)
#include<iostream>
using namespace std;
class student
{
public:
void initdata(string name, int age)
{
//区分法一:类名限定
student::name = name;
//区分法二:this
this->age = age;
}
void print()
{
cout << this->age << endl;
}
student& returnstudent()
{
return *this;
}
protected:
int age;
string name;
};
int main()
{
student wbm;
wbm.initdata("wbb", 18);
wbm.returnstudent().returnstudent().returnstudent().print();
//套大娃。
return 0;
}