C++类开始的重新学习记录1

C++类开始的重新学习记录1

欢迎大家指出不足和错误之处
标记处是坑点或者说面试点

第一部分——基础

1、c++的特点
-继承——减少代码工作量
-封装——保护成员变量
-多态——一类中的多种实现

2、类的构造函数

class object
{
//公共属性(提供外部接口)
public:
	//无参构造函数
	object();
	//有参构造函数
	object(int num);
	//拷贝构造函数
	object(const object &obj);
//私有属性(类外部不可访问)
private:
	int m_Num;
};

int main()
{
	//调用的是无参构造函数
	object ob1;
	//调用的是有参有参构造函数
	object ob2(10);
	//调用的是拷贝构造函数
	object ob3(ob2);
	
	return 0;
}

三种调用拷贝函数的时机

//用A赋值B
object A;
object B(A);
//函数的参数是类
void func(object obj1)
{
	//code here
}
//返回值是类
object func()
{
	//code here
}

拷贝构造——函数浅拷贝与深拷贝问题
先看一个发生异常的例子

class object
{
public:
	object();
	object(int num)
	{
		m_Num = new int(num);
	}
	~object()
	{
		if (m_Num != NULL) {
			delete m_Num;
			m_Num = NULL;
		}
	}
private:
	int *m_Num;
};

int main()
{
	object ob1(10);
	object ob2(ob1);
	return 0;
}

问题是什么呢,浅拷贝导致内存重复释放
解决方法就是使用深拷贝——自己写拷贝构造函数

object(const object &ob1)
{
	//如果不空则释放内存并置空
	if (m_Num != NULL) {
		delete m_Num;
		m_Num = NULL;
	}
	//重新申请内存
	//拷贝后的内存地址不同
	m_Num = new int(*ob1.m_Num);
}

3、析构函数
1、没有任何参数
2、在类释放前会执行
3、如果不写,编译器默认加上一个空的函数

class object
{
public:
	object();
	//析构函数
	~object()
	{
		//code here
	}
private:
	int m_Num;
};

4、类的组合
指的是类中可以包含其他类

class a;
{
public:
	a();
	~a();
private:
	//a作为b的成员变量
	int m_Num;
}

class b
{
public:
	b();
	~b();
private:
	//a作为b的成员变量
	class a;
}

执行过程
a构造——b构造
b析构——a析构
内部先构造,外部先析构
5、静态static
1、空类占用1Byte
2、只有非静态成员函数在类中

class object
{
public:
	void func()
	{
		//code here
	}
private:
	int m_Num1;
	static int m_Num2;
};

void test()
{
	object ob1;
	//输出值为4
	cout << sizeof(ob1) << endl;
}

6、常量const
1、this指针是指针常量,指向不可改
2、常量函数只能访问常量成员变量
3、mutable是特殊变量修饰,可在const函数中修改
7、友元
1、友元全局函数

class A
{
	//在类中声明友元函数func
	friend void func();
public:
	A();
	~A();
private:
	int m_Num;
}

void func()
{
	A a;
	//此时可以访问类中private成员
	cout << a.m_Num << endl;
}

2、友元类

class A;

class B
{
public:
	B()
	{
		A a;
		this->m_Num = a.m_Num;
	}
	~B();
private:
	int m_Num;
};

class A
{
	//在类中声明B,B就可以单向访问A
	friend B;
public:
	A();
	~A();
private:
	int m_Num;
}

3、友元成员函数

class A;
class B
{
public:
	B();
	~B();
	void func();
private:
	int m_Num;
};

class A
{
	//在类中声明B,B就可以单向访问A
	friend void B::func();
public:
	A();
	~A();
private:
	int m_Num;
};

void B::func()
{
	A a;
	m_Num = a.m_Num;
}

8、运算符重载
1、算符重载(以+为例)
成员函数实现

class MyInt
{
public:
	MyInt()
	{
		m_Int1 = 0;
		m_Int2 = 0;
	}
	MyInt(int num1, int num2) : m_Int1(num1), m_Int2(num2) {}
	
	int GetInt1()
	{
		return m_Int1;
	}
	int GetInt2()
	{
		return m_Int2;
	}
private:
	int m_Int1;
	int m_Int2;
};

//成员内实现运算符重载
MyInt& MyInt::operator+(MyInt num2)
{
	MyInt temp;
	temp.m_Int1 = this->m_Int1 + num2.m_Int1;
	temp.m_Int2 = this->m_Int2 + num2.m_Int2;
	return temp;
}

全局函数实现

MyInt& operator+(MyInt num1, MyInt num2)
{
	MyInt temp;
	temp.m_Int1 = num1.m_Int1 + num2.m_Int1;
	temp.m_Int2 = num1.m_Int2 + num2.m_Int2;
	return temp;
}

2、左移运算符重载<<
只能用全局函数实现
否则无法达到cout在<<左边的效果

ostream& operator<<(ostream &cout, MyInt &num)
{
	cout << num.m_Int1 << " " << num.m_Int2;
	return cout;
}

3、自增运算符
前置++i

MyInt& operator++()
{
	m_Int1++;
	m_Int2 += 2;
	return *this;
}

后置i++
注意:不允许链式计算及i++++计算没有意义

//int 站位参数,区别后置自增
MyInt operator++(int)
{
	MyInt temp = *this;
	m_Int1++;
	m_Int2 += 2;
	return temp;
}

4、关系运算符
以==为例,!=就将返回值互换即可

bool operator==(MyInt num2)
{
	if (m_Int1 == num2.m_Int1&&m_Int2 == num2.m_Int2) {
		return true;
	}
	else
	{
		return false;
	}
}

5、()函数运算符重载——仿函数
称其为仿函数的原因是调用和函数没有区别

//参数很多样化
MyInt operator()(int num)
{
	//code here
}

6、赋值运算符=
如果不重载=运算符,在执行ob1 = ob2时会调用拷贝函数
会引发深浅拷贝的问题(详见构造-拷贝)

MyInt& operator=(MyInt num2)
{
	m_Int1 = num2.m_Int1;
	m_Int2 = num2.m_Int2;
	return *this;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值