友元
友元可分为
- 外部函数友元,外部函数访问类中的私有属性
- 成员函数友元,
- 类友元
友元的特点:
- 不具有自反性
- 不具有传递性
- 不具有继承性
如果一个类是另外一个类的友元,那么这个类中的方法就可以访问另外一个类中的私有和保护成员属性。
总结:
- 友元函数不是类的成员函数,在函数体中访问对象的成员,必须用对象名加运算符“.”加对象成员名,但友元函数可以访问类中的所有成员。一般函数只能访问公有成员。
- 友元函数不受类的访问权限关键字的限制,可以把它放在类的共有,私有,保护,部分,结果都一样。
- 某类的友元函数的作用域,并非该类的作用域,如果该友元函数是另外一个类的成员函数,其作用域为另一个类的作用域,否则与一般函数相同。
. using namespace std;
//友元
class Object;
class Int
{
//类友元
//friend class Object;
//成员函数友元
friend void Object::Get_val(const Int& it);
private:
int value;
public:
Int(int x = 0) :value(x) { cout << "Create Int" << this << endl; }
// Int(int x) :value(x) {}
~Int(){cout << "Destory Int" << this << endl;}
//外部函数友元
friend void Print(const Int& it);
};
class Object
{
public:
void Get_val(const Int& it);
};
void Print(const Int& it)
{
cout << it.value << endl;
}
int main()
{
Int a(10);
Print(a);
Object obj;
obj.Get_val(a);
return 0;
}
静态成员(为单例模式做准备)
静态成员:
- 存储在数据区
- 多次调用,只初始化一次。
- 生存期:整个程序结束,才被回收。
- 静态成员变量的访问可以不依赖对象(不依赖于this指针)
静态成员属性
重点:
- 必须在类外进行初始化。
- 不能以列表方式进行初始化,不能在构造函数或者拷贝构造函数中进行初始化。
如果没做到以上两点:
如下:
class person
{
public:
static int num;
//错误初始化静态成员变量
person(int num)
{
this->num = num;
cout << "构造" << endl;
}
~person()
{
cout << "析构" << endl;
}
};
int main()
{
person p1(1);
return 0;
}
正确:
int person::_num=1;
注意:
- 函数凡是没有this指针的都不能加const。
- 由于静态函数没有this指针,所以不能在函数后面加const进行修饰。
class Object
{
static int num;
int value;
public:
Object(int x = 0) :value(x) { num = 1; }
Object(const Object& obj) :value(obj.value) { num + 1 };
~Object() { num -= 1; };
int print()const
//int print(const Object *const this)
{ //无法对value进行修改,因为this的指向能力被const销了
//而num数据静态变量在数据区,因此受this的约束,this也访问不到。
num += 10;
cout << "value" << this->value << "num" << num << endl;
}
static int show()const//(如上图)
{
num + = 10;
cout << "value" << this->value << "num" << endl;
}
};
//类外初始化静态成员变量
int Object::num = 0;
int main()
{
Object obja(10);
obja.print();//print(&obja);
obja.show();//访问不到,因为show属于静态成员函数
}
也不能打印value,静态成员方法只能使用静态成员变量。不能访问到非静态成员属性,原因是没有this指针的存在,没办法访问到某个对象(this指针指向对象,对象才能访问类中的成员属性)。
判断下列是能够通过编译:
auto:类型指示符
可以根据 初始值 推演出其类型。
- 变量必须初始化才能进行类型推演
- 一个变量对应一个auto,否则会导致二义性。
- 使用auto声明的变量必须有初始化值,以让编译器推断出它的实际类型,并在编译时将auto占位符替换成真正的数据类型。
int main()
{
auto x = 5; //x: int
const auto *xp = &x;//xp const int *;auto:const int
const auto *xp = &x,u=6; //变量必须初始化才能进行类型推演
//一个变量对应一个auto,否则会导致二义性。如上
auto ip = &x//ip:int *
auto *sp = &x //sp int* auto:int
}
引用:
int main()
{
const int a= 10;
auto b = a; //b = int auto: int
auto&c = a; //c = const int & auto:const int
}
指针:
int main()
{
const int a = 10;
auto *p = &a; //p : const int * atuo:const int
}
简写模板类:
void fun(auto x) //可以推演出任意的类型
{
cout<<"x type:"<<typeif(x).name()<<endl;
cout<<x<<endl;
}
int main()
{
func(12);
func(12.23);
func('a');
int x =10;
func(&x);
return 0;
}