C++ 基础知识 之 类

类的基本思想是数据抽象封装

构造函数特点

构造函数是一种比较特殊的成员函数,用于创建并初始化对象。声明对象时构造函数被编译器自动调用。
构造函数的特点:
(1)构造函数的访问权限必须为共有;
(2)构造函数名和类名相同;
(3)构造函数没有返回值;
(4)构造函数可以带参数,用于初始化成员变量;
(5)不同的构造函数之间必须在参数数量和参数类型上有所不同;
(6)构造函数在const对象的构造过程中向其写值,例如**初始化列表**中的示例;

默认构造函数

默认构造函数分两种:
1.构造函数无需任何参数;
2.构造函数带参数但参数都有默认值;

Example codes:
Demo();
Demo(int a = 0,int b = 0);
Demo(int a,int b);

默认构造函数是指在声明对象时,可以不传参数,使用空值或默认值对对象进行初始化,而普通构造函数在声明时必须传递参数,否则构造函数的参数,没有值。
如果我们的类没有显示地定义构造函数,那么编译器就会为我们隐式地定义一个默认的构造函数。编译器创建的构造函数被称为合成的默认构造函数

C++11新关键字default

认构造函数并不一定都是编译器隐式地提供的,而有可能是用户自己写出来的,前提是用户本来已经写过了其他的构造函数,但是仍然需要这样的一个默认构造函数的时候,就需要用户自己进行书写,此时没有参数的构造函数就是构造函数,但是如果想要此时的构造函数和原来因为没有定义构造函数而被编译器隐式定义的合成的默认构造函数一样的话,只需要在声明后面写一个=default就可以了。

例:

class Demo{
publicDemo() -default;
	Demo(int a,int b)x(a),y(b);

这样的方式来声明无参数构造函数,会带来一个问题,就是使得 其不再是 POD 类型,因此可能让编译器失去对这样的数据类型的优化功能。这是我们不希望看到的。因此最后使用 = default来修饰默认构造函数
注:
POD全称Plain Old Data。通俗的讲,一个类或结构体通过二进制拷贝后还能保持其数据不变,那么它就是一个POD类型。

构造函数初始化列表

Demo(int a,int b):x(a),x(b)
1.对类类型的成员,使用初始化列表效率更搞。
2.如果成员是const,引用,或者属于某种未提供默认构造函数的类类型,我们必须通过构造函数初始化列表为这些成员提供初始值。

class Demo{
publicDemo(int a,int b)x(a),y(b);
private:
	const int x;
	int &y;
}

3.在继承时,子类的构造函数中初始化父类的成员时。

析构函数

销毁对象时系统会自动调用一个函数进行清理工作(回收对象所占用的内存空间),这个函数被称为析构函数。
特点:
1.无返回值
2.无参数
3.不可以被重载
4.必须公有

**

拷贝构造函数

  • 浅拷贝
    可以把一个对象赋值给另外一个对象,对象的每个成员值,一对一的拷贝到新的对象。如果对象含有指针成员变量,而指针变量又指向堆空间,将只拷贝指针成员变量本身的值,造成俩个对象的指针指向同一堆内存,删除对象时候造成二次删除。

    1.位拷贝,拷贝构造函数,赋值重载
    2.多个对象共用同一块资源,同一块资源释放多次,崩溃或者内存 泄漏
    3.缺省拷贝构造函数在拷贝过程中是按字节复制的,对于指针型成 员变量只复制指针本身,而不复制指针所指向的目标
    4.值适用只有基本构造函数

  • 深拷贝
    每个对象共同拥有自己的资源,必须显式提供拷贝构造函数和赋值运算符。

class String
{
public:
	String(const char* str = "")
		:_str(new char[strlen(str) + 1])
	{
		strcpy(_str,str);
	}
	String(const String& s)
		:_str(NULL)//拷贝构造函数
	{
		String tmp(s._str);//调用这个构造函数,开辟空间,建立一个和s1一样大小的空间,并拷贝值
		swap(_str,tmp._str);
	}
	String& operator=(String s)  // 相当与 String str1=str2;
	{
		swap(_str,s._str);//交换函数,好处:不用担心交换变量精度的缺失,无需构造临时变量,不会增加空间复杂度
		return *this;
	}
	~String()
	{
		delete[] _str;
	}
private:
	char* _str;
}

函数重载

在同一个作用域中,可以有一组具有相同函数名,不同参数列表的函数,被称为重载函数。参数列表不同是指参数的个数或参数的类型不同。
例:

void Demo();
void Demo(int i);
void Demo(float i);

如果仅仅是函数的返回值类型不同,不能是函数的重载。因为在函数调用时不知道调用那个函数。

void Demo(int x);
int Demo(int x)

友元

类可以允许其他类或者函数访问它的非公有成员,方式是令其他类或函数成为他的友元
优点:提高了运行效率;
缺点:破坏了应用的封装性;

友元类

如果类B是类A的友元,那么友元类B的所有成员函数都是A类的友元函数。


class A{
public:
	int GetX() { return x; }
	friend class B;//B类是A类的友元类
	//其它成员略
private:
	int x;
};
class B{
public:
	void set(int i);
	//其他成员略
private:
	A a;
};
void B :: set(int i){
	a.x = i;//由于B类是A类的友元类,所以在B的成员函数中可以访问A类对象的私有成员
	}
}
  • 友元的关系是单向的,而不是双向的。如果声明了类B是类A的友元类,不等于类A也是类B的友元类,类A中的成员函数不能访问类B中的私有数据;
  • 友元的关系不能传递或继承,如果类B是类A的友元类,类C是类B的友元类,不等于类C是类A的友元类。如果想让类C是类A的友元类,必须显式地在类A中另外声明;

友元函数

友元函数是在类中用关键字friend修饰的非成员函数,可以通过对象名访问类的私有成员和保护成员。

class Point{
public:
	Point(int xx = 0, int yy = 0) { X = xx; Y = yy;}
	int GetX() {return X;}
	int GetY() {return Y;}
	friend float fDist( Point &a, Point &b );
private:
	int X, Y;
};
 
float fDist(Point &p1, Point &p2){
	double x = double(p1.X - p2.X);//通过对象访问私有数据成员,而不是必须使用Getx()函数
	double y = double(p1.Y - p2.Y);
	return float(sqrt(x*x + y*y));
}
int main(){
	Point p1(1, 1), p2(4, 5);
	cout << "the distance is:";
	cout << fDist(p1, p2) << endl;//计算两点之间的距离
	return 0;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值