C++的一些特性(3)

列表初始化

用一对大括号可以给一个数组,结构体,甚至是对象成员初始化。

数组

1
2
3
4
5
6
7
#include<iostream>
using namespace std;
char s[] = {'x','i','a','0','j','i','2','3','3'};
int main() {
puts(s);
system("pause");
}

结构体

初始化,传参,返回都可以。

初始化结构体

1
2
3
4
5
6
7
8
9
10
11
#include<iostream>
using namespace std;
typedef struct __Info {
int a;
double b;
}Info, * PInfo;
int main() {
Info s = { 1,1.5 };
printf("%d %lf\n", s.a, s.b);
system("pause");
}

传参

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
using namespace std;
typedef struct __Info {
int a;
double b;
}Info, * PInfo;
void func(Info s) {
printf("%d %lf\n", s.a, s.b);
}
int main() {
func({ 1,1.5 });
system("pause");
}

返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
using namespace std;
typedef struct __Info {
int a;
double b;
}Info, * PInfo;
Info func() {
return { 1,1.5 };
}
int main() {
//func({ 1,1.5 });
Info s = func();
printf("%d %lf\n", s.a, s.b);
system("pause");
}

对象

成员变量初始化

1
2
3
4
5
6
7
8
9
10
#include<iostream>
using namespace std;
class A {
public:
int n{ 1 };
std::string s{ "123" };
};
int main() {
system("pause");
}

函数属性声明

可以在声明函数之后跟一个 = xxx 来声明一个函数的属性,default 表示显式缺省函数,delete 表示显式删除函数,前面还学到过 =0 表示纯虚函数,如果定义为已删除的话就不能够使用这个函数了。

例如:需要禁止拷贝构造函数的使用。以前通过把拷贝构造函数声明为private访问权限,这样一旦使用编译器就会报错。

而在C++11中,只要在函数的定义或者声明后面加上”= delete”就能实现这样的效果(相比较,这种方式不容易犯错,且更容易理解)

联合体的性质

联合体每个不同的定义共用内存,一般来说一个定义只能为基础类型而不能为复杂类,如果要包含复杂类,则需要在联合体内实现构造函数和析构函数让它能被处理。

类的一些其它性质

指定父类构造函数

之前有遇到过,在继承的关系中,我们生成派生类必须调用父类的构造函数,但是却不能指定调用,就会很难受,今天知道了如何指定调用父类的构造函数,之前我是使用了 Child.father::father() 的形式调用,但是出现了巨多的问题,实际上我们指定去调用父类的构造函数可以这么写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
using namespace std;
class A {
public:
A() {
std::cout << "A无参构造" << std::endl;
}
A(int x,double y) {
n = x;
d = y;
std::cout << "A带参构造" << std::endl;
};
int n;
double d;
};
class B:public A
{
public:
B() {
std::cout << "B无参构造" << std::endl;
}
B(int x, double y) :A(x, y) {
std::cout << "B带参构造" << std::endl;
}
~B() {};
};
int main() {
B obj(1, 2.5);
system("pause");
}

构造函数继承

在类当中我们可以 using 父类的构造函数以便于我们不需要写子类的构造函数,这么写的作用是告诉编译器我需要编译器自动产生所有的转发函数,这行为就叫继承构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<iostream>
using namespace std;
class A {
public:
A() {
std::cout << "A无参构造" << std::endl;
}
A(int x,double y) {
n = x;
d = y;
std::cout << "A带参构造" << std::endl;
};
int n;
double d;
};
class B:public A
{
public:
using A::A;
B() {
std::cout << "B无参构造" << std::endl;
}
~B() {};
};
int main() {
B obj(1, 2.5);
system("pause");
}

委托构造

比如有一个对象,它有两个成员,我希望默认构造的情况下委托带参构造帮我初始化某些成员,那么可以在默认构造后面加上那个带参构造委托它来完成构造。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
using namespace std;
class A {
public:
A():A(0,0) {
std::cout << "A无参构造" << std::endl;
}
A(int x,double y) {
n = x;
d = y;
std::cout << "A带参构造" << std::endl;
};
int n;
double d;
};
int main() {
A obj;
system("pause");
}

练习:手写STL库

就随便写一个阉割版的 vector 吧,实现了基本的插入删除功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#pragma once

template<typename T>
class Vector
{
public:
Vector();
Vector(int n);
~Vector();
void InitArray(int n);
int length();
T& operator[](int index);
void push_back(T val);
T pop_back();
bool empty();

public:
T* base;
int len;
int top;
};

template<typename T>
inline Vector<T>::Vector()
{
this->InitArray(5);
}

template<typename T>
inline Vector<T>::Vector(int n)
{
this->InitArray(n);
}

template<typename T>
inline Vector<T>::~Vector()
{
delete this->base;
}

template<typename T>
inline void Vector<T>::InitArray(int n)
{
this->base = new T[n];
this->len = n;
this->top = 0;
}

template<typename T>
inline int Vector<T>::length()
{
return this->top;
}

template<typename T>
inline T& Vector<T>::operator[](int index)
{
return this->base[index];
}

template<typename T>
inline void Vector<T>::push_back(T val)
{
if (this->top == this->len) {//add 32
T* tmp = new T[this->len + 32];
memcpy(tmp, this->base, this->len * sizeof(T));
delete this->base;
this->base = tmp;
this->len += 32;
}
this->base[top++] = val;
}

template<typename T>
inline T Vector<T>::pop_back()
{
if (top == 0)return T();
return this->base[--top];
}

template<typename T>
inline bool Vector<T>::empty()
{
return this->top == 0;
}