目录
必须在初始化列表初始化的条件:
explicit
多参数强制类型转换
静态成员
编辑
对于静态成员变量需要在构造函数里初始化吗?
静态成员函数:
题目1:
求1+2+3+...+n_牛客题霸_牛客网 (nowcoder.com)
要求类对象只能在栈上:
1:const修饰的成员变量(只有一次初始化的机会,发生在定义的时候,也就是初始化列表
2:引用:(要变成其他变量的别名,只有一次初始化的机会,发生在定义,也就是初始化列表。
3:自定义类型成员(且该类没有默认构造)
例如:
#include
using namespace std;
class A
{
public:
A(int a)
{
_a = a;
}
private:
int _a;
};
class B
{
public:
B()
{
}
private:
int _b;
A a;
};
我们不运行也会报错 :如果没有在初始化列表中写的话,对于自定义类型A会调用其默认构造,因为类A没有默认构造,所以报错。
class Date
{
public:
Date(int year)
:_year(year)
{}
Date& operator=(const Date&d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2022);
Date d2 = 2022;
return 0;
}
隐式类型转换。
类比这里:
把整型i传递给一个临时变量,该临时变量的类型是double,再把该临时变量赋值给d。
这里也是同样,把2022强制类型转换为Date类型传递给临时变量,再把该临时变量传递给d5.
这里无法优化:这里是引用,必须用2022先构造一个对象,再用该对象引用。
explicit Date(int year)
:_year(year)
{}
我们在构造函数前面加上了explicit,就不会发生这些隐式类型转换:
Date(int year,int month=1,int day=1)
:_year(year)
, _month(month)
, _day(day)
{}
这种半缺省,只用传一个参数的也支持隐式类型转换。
全缺省的也可以。
class Date
{
public:
Date(int year,int month,int day)
:_year(year)
, _month(month)
, _day(day)
{}
Date& operator=(const Date&d)
{
if (this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
/*Date d1(2022);
Date d2 = 2022;
const Date&d5 = 2022;*/
Date d1 = { 2022, 10, 12 };
Date d2(2022, 10, 12);
return 0;
}
int main()
{
/*Date d1(2022);
Date d2 = 2022;
const Date&d5 = 2022;*/
Date d1 = { 2022, 10, 12 };
Date d2(2022, 10, 12);
const Date&d3 = { 2022, 10, 13 };
return 0;
}
class A
{
public:
A(int a = 0)
:_a(a)
{
;
}
private:
int _a;
};
int main()
{
A aa1(1);
A aa2 = 2;
return 0;
}
我们想要计算一共创建了多少个A类的对象。
int N = 0;
class A
{
public:
A(int a = 0)
:_a(a)
{
+ +N;
}
A(const A&aa)
:_a(aa._a)
{
++N;
}
private:
int _a;
};
int main()
{
A aa1(1);
A aa2 = 2;
cout << N << endl;
return 0;
}
只有构造和拷贝构造可以创建对象:
int N = 0;
class A
{
public:
A(int a = 0)
:_a(a)
{
++N;
}
A(const A&aa)
:_a(aa._a)
{
++N;
}
private:
int _a;
};
int main()
{
A aa1(1);
A aa2 = 2;
A aa3 = aa1;
cout << N << endl;
return 0;
}
int N = 0;
class A
{
public:
A(int a = 0)
:_a(a)
{
++N;
}
A(const A&aa)
:_a(aa._a)
{
++N;
}
private:
int _a;
};
void f(A aa)
{
}
int main()
{
A aa1(1);
A aa2 = 2;
A aa3 = aa1;
cout << N << endl;
f(aa1);
cout << N << endl;
return 0;
}
验证了传值传参就是拷贝构造。
int N = 0;
class A
{
public:
A(int a = 0)
:_a(a)
{
++N;
}
A(const A&aa)
:_a(aa._a)
{
++N;
}
private:
int _a;
};
void f(A aa)
{
}
A f1()
{
A aa;
return aa;
}
int main()
{
A aa1(1);
A aa2 = 2;
A aa3 = aa1;
cout << N << endl;
f(aa1);
cout << N << endl;
f1();
cout << N << endl;
return 0;
}
传值返回也是一次拷贝构造。
尽量避免使用全局变量:
全局变量在哪里都可以修改。
类里的静态受到类域的限制。
#include
using namespace std;
class A
{
public:
A(int a=1)
:_a(a)
{
;
}
private:
int _a;
static int N;
};
int main()
{
A aa1(1);
A aa2 = 2;
A aa3 = aa1;
}
aa1和aa2中有静态成员变量N吗?
总结:静态成员变量不存在于类对象里,存在于静态区。
答:不需要,因为静态成员变量是每一个对象都共享的,每一次构造都对静态成员都会对静态成员变量进行修改。
静态成员变量的定义:
在全局定义,需要加上类域。
只能在类里面使用静态成员变量。
静态成员变量的生命周期是全局的,作用域受类域限制
当静态成员变量是公有的时候,也是可以在类外面访问的
#include
using namespace std;
int A::N = 0;
class A
{
public:
A(int a=1)
:_a(a)
{
N++;
}
private:
int _a;
public:
static int N;
};
int main()
{
A aa1(1);
A aa2 = 2;
A aa3 = aa1;
cout << A::N << endl;
cout << aa1.N << endl;
}
对于静态成员变量为私有的情况,设置一个成员函数取出静态成员变量。
int GetN()
{
return N;
}
如果我们想得到静态成员变量,使用静态成员函数没有对象也可以调用。
静态成员函数只能访问静态成员(没有this指针)
class Sum
{
public:
Sum()
{
_ret+=_add;
_add++;
}
static int GetRet()
{
return _ret;
}
private:
static int _ret;
static int _add;
};
int Sum::_ret=0;
int Sum::_add=1;
class Solution {
public:
int Sum_Solution(int n) {
Sum A[n];
return Sum::GetRet();
}
};
class A
{
public:
A(int a =0)
:_a(a)
{
}
private:
int _a;
};
class A
{
public:
A GetObj(int a = 0)
{
A aa(a);
return aa;
}
private:
A(int a =0)
:_a(a)
{
}
private:
int _a;
};
int main()
{
A aa3 = GetObj();
return 0;
}
我们要调用函数GetObj,就需要先创建对象,我们要创建对象,就得先调用函数,产生矛盾。
class A
{
public:
static A GetObj(int a = 0)
{
A aa(a);
return aa;
}
private:
A(int a =0)
:_a(a)
{
}
private:
int _a;
};
int main()
{
A aa3 = A::GetObj();
return 0;
}
我们可以用静态函数,静态函数不需要对象也可以调用。