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() { 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) { 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; }
|