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;
}