【c++】类------构造函数,友元类,友元函数,隐式类型转换,静态成员

一、定义抽象数据类型

在这里插入图片描述

  • 每一个非静态成员函数都有一个隐式的this形参,当某个对象调用成员函数时,其实是通过类名调用成员函数,然后把对象地址传递给this形参。
  • 常量对象不能调用普通的成员函数。这是因为普通成员函数中隐式形参this是一个指向非常量的常量指针,也就是说它指向的地址不变,但是地址所在内存中的数据可以发生变化。但是常量对象的指针是指向常量空间的,也就是对象所在内存数据不能发生变化。所以不能将常量对象地址赋给非指针常量。具体解释如下:
    在这里插入图片描述
  • this解指针以后返回对象的引用。
    在这里插入图片描述
    在这里插入图片描述

构造函数

  • 我们创建const对象时,直到构造函数完成初始化过程,对象才能取得其const属性,也就是说构造函数在const对象构造构成中可以向其写值。
  • 只有在类没有定义任何构造函数的情况下,编译器才会为类定义默认构造函数。也就是说,如下代码会出错:
#include 
using namespace std;
class MyClass{
private:
	int val_;
	MyClass(int val):val_(val){}
};
int main()
{
	MyClass mycls;//no matching function for call to ‘MyClass::MyClass()’
	return 0;
}

  • 合成默认构造函数按照如下规则处理类的数据成员:
    • 如果有初始值,那么用初始值初始化。
    • 如果没有初始值,并且是内置类型或者复合类型,那么其未定义。如果是用户定义类型,则使用其默认构造函数来初始化。
      如下类中两个数据成员,val_是未定义,也就是它的值是随机的。
class MyClass{
public:
	int val_;
	string str_;
};

在这里插入图片描述
在这里插入图片描述

  • 下面的声明是说,默认构造函数使用系统生成的默认构造函数。-c++11新特性。
    在这里插入图片描述

拷贝、赋值和析构

在这里插入图片描述
在这里插入图片描述

  • 友元函数需要在类外部进行再次声明。
#include 
using namespace std;
class MyClass{
private:
	int val_;
	string str_;
public:
	MyClass(int val = 0,string str = ""):val_(val),str_(str){}
	friend void print(ostream &os, MyClass& cls)
	{
		os<<cls.val_<<" "<<cls.str_<<endl;
	}
	friend MyClass add(MyClass& cls1, MyClass& cls2)
	{
		MyClass res;
		res.val_ = cls1.val_ + cls2.val_;
		res.str_ = cls1.str_ + cls2.str_;
		return res;
	}

};
void print(ostream &os, MyClass& cls);
MyClass add(MyClass& cls1, MyClass& cls2);
int main()
{
	MyClass cls(100, "123"), cls2(10,"456");
	cls = add(cls,cls2);
	print(cout,cls);
	return 0;
}

类的其它特性

  • 定义一个类型成员:可以在类内部使用typedef或者using定义一个类型别名,但是需要注意,这个类型的定义必须在使用之前。
class Screen{
public:
	typedef size_t pos;
private:
	pos cursor = 0;
	pos height = 0, width = 0;
	string contents = "";
};
  • 不再初始化列表中的成员数据将会被赋予默认初始值(注意不是值初始化),如果没有类内初始值,那么需要显示赋值。
  • mutable可以让任何变量永远不会是const的。
  • 返回类型声明为引用,然后返回*this的好处是好几个成员函数可以连续调用,比如Obj.fun1().fun2().fun3
    在这里插入图片描述
  • 内联函数的优点,运行时开销更小。
  • 类在只声明未定义的情况下,可以使用其引用和指针,不能建立对象。
  • 将一个类声明为另一个类的友元。
  • 每个类自己决定允许哪些函数或者类来访问自己的私有成员。
    在这里插入图片描述
  • 类的成员函数可以调用非成员函数。
  • 类成员函数体是在类整个可见后才进行处理,处理过程中,如果名字所在块中没有找到相应的声明,那么会继续向外层查找,如果一直没有找到,那么保存未定义。
  • 使用作用于外的变量:
    【c++】类------构造函数,友元类,友元函数,隐式类型转换,静态成员_第1张图片
    【c++】类------构造函数,友元类,友元函数,隐式类型转换,静态成员_第2张图片

构造函数再探

构造函数初始值列表

  • 如果数据成员是引用、const类型或者是未提供默认构造函数的类类型,那么我们必须在初始化列表对其进行初始化。
    【c++】类------构造函数,友元类,友元函数,隐式类型转换,静态成员_第3张图片
  • 初始化顺序和成员声明顺序有关和初始化列表顺序无关。
    在这里插入图片描述
  • 下列行为是不合法的,会导致有两个默认构造函数:
#include 
using namespace std;
struct X{
	X(int i=10, int j = 20):base(i),rem(base%j){}
	X(string str = ""){}
	int rem,base;
};
int main()
{
	X x(1,2);
	X xa;
	return 0;
}

在这里插入图片描述

  • 委托构造函数:
#include 
using namespace std;
class MyClass{
private:
	int val_;
	string str_;
public:
	MyClass(int val, string str):val_(val), str_(str){
		cout<<"1"<<endl;
	}
	MyClass(int val):MyClass(val,""){
		cout<<"2"<<endl;
	}
	MyClass():MyClass(0,""){
		cout<<"3"<<endl;
	}
};
int main()
{
	MyClass mcls;
	cout<<endl;
	MyClass cls1(1,"123");
	cout<<endl;
	MyClass cls(3);
	return 0;
}

在这里插入图片描述
【c++】类------构造函数,友元类,友元函数,隐式类型转换,静态成员_第4张图片

隐式类类型转换

  • 允许一步类类型转化:
    如果说类定义了接收某种类型的构造函数,那么接收类引用的函数,在调用时可以直接传入构造函数需要的类型
#include 
using namespace std;
class MyClass{
public:
	MyClass(){}
	MyClass(string str){//前面加上explicite可以抑制隐式调用
		cout<<"Hi"<<" "<<str<<endl;
	}
	void fun(const MyClass& cls){}
};
int main()
{
	string str = "123";
	MyClass mycls;
	mycls.fun(str);

}

在这里插入图片描述
【c++】类------构造函数,友元类,友元函数,隐式类型转换,静态成员_第5张图片

聚合类

  • 符合下面条件的类称为聚合类
    - 所有的成员都是public的
    - 没有定义任何构造函数
    - 没有类内初始值
    - 没有基类也没有virtual函数
  • 使用初始化列表来初始化成员数据。
#include 
using namespace std;
struct MyStruct{
int val_;
string str_;
};
int main()
{
	MyStruct msru = {1,"23"};
	return 0;

}

字面值常量类

类的静态成员

在这里插入图片描述

#include 
using namespace std;
class MyClass{
public:
	static int s_val_;
	string str = "123";
public:
	void myFunc()
	{
		cout<<"NoStatic"<<s_val_<<endl;
	}
	static myStaticFunc()
	{
		cout<<"static"<<str<<endl;//出错
	}
};
int MyClass::s_val_ = 20;
int main()
{
	cout<<MyClass::s_val_<<endl;
	MyClass cls;
	cls.myFunc();
	return 0;
}

你可能感兴趣的:(C语言/C++)