抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

构造函数&析构函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//构造方法
//法1
class A{
A(){...} //构造函数
~A(){...} //析构函数
}

//法2
class A{
A();
~A();
}

A::A(){...}
A::~A(){...}
//法3
class A{
int a,b;
A():a(),b(){} //构造函数初始化列表,只能对非静态成员初始化,a(),b()表示括号里的赋给外的
}

c++中貌似会用很多指针!!

​ *p p->

继承

1
2
//继承方法
class B:public A{}

访问限制

​ private:private成员只能由类成员(类内,类外main什么的就不)和友元(friend)访问
​ protected:子类能用
​ friend(友元):?

内联函数inline

1
2
3
4
5
6
7
8
9
10
11
//目的...
//内联函数和普通函数的区别在于:当编译器处理调用内联函数的语句时,不会将该语句编译成函数调用的指令,而是直接将整个函数体的代码插人调用语句处
inline void func(){cout<<"hh";} //用inline关键字修饰

int main(){
func();
}
//相当于
int main(){
cout<<"hh";
}

覆盖&隐藏

1
2
3
4
5
6
7
8
9
10
11
12
//※虚函数 virtual用法
overriding(覆盖)
特征:
1.子类覆盖父类函数
2.函数名和参数名都相同
3.父类被覆盖函数是虚函数(virtual),因为如果不是(virtual)的那就会发生namehidden

namehidden(隐藏)
特征:
1.子类隐藏了父类的函数(还存在)
2.子类与父类函数名相同但参数不同的父类函数将被隐藏
3.子类函数与父类函数的名称相同,参数也相同,但是父类函数没有(virtual),父类函数被隐藏,故如果向上转型,将仍然调用的是子类的方法

re?C++抽象类

1.含有虚拟函数的类称为抽象类&&不能生成实例
2.纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”
3.如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个 抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了

1
//纯虚函数的写法->virtual (返回类型) (名) = 0;

const* vs *const

1
2
3
4
5
6
7
//主要看const是在*前还是*后
1.const*的情况,const在前修饰*
=> *是什么?是指针。指针是什么?指针是有指向的,代表指向的那个东西。故const在*前就是指针是const的,即指向的那个东西是const的,所以不能在=别的。

2.*const的情况,const在*后修饰后面的变量
=> 那。。那个变量是什么呢?是地址。所以一个const的地址就是说初始化后b不能在改变,也就是b不能在等于别的&a
int *const b = &a; //初始化是取出地址初始化的嘛,所以b就是那个地址,前面的int *const都是修饰b的

extern

​ extern也可用来进行链接指定;也可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
即有以下两个作用:
​ 1.与“C”连用,如extern “C” void fun();告诉编译器按C的规则去翻译
​ 2.修饰声明全局变量或函数,其声明的变量和函数可以在其它模块中使用,注意,这只是一个声明而不是定义,具体的定义要在具体的定义中完成

类中 f() const ? f() ==>类是const时用f() const那个(类似重载)

引用

1
2
3
4
5
6
7
8
9
10
11
12
定义:
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

引用vs指针:
1.不存在空引用。引用必须连接到一块合法的内存。
2.一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
3.引用必须在创建时被初始化。指针可以在任何时间被初始化。

引用创建:
//
char a;
char& b = a;//1.必须初始化 2.指向对象(a)以存在

拷贝构造

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
### 
c++初始化用()和用=是等价的;如A的构造函数A(int x)可以A(10)也可A = 10,同理其他类型!!!所以初始化一个类,如A a时 A a = b;相当于用b来初始化a(默认是复制粘贴成员(private的不会复制),但也可把他重写A(const A& x){}这个重载就叫拷贝构造;
好习惯 写个类就写一个拷贝构造
###


拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:
1.通过使用另一个同类型的对象来初始化新创建的对象。
2.复制对象把它作为参数传递给函数。
3.复制对象,并从函数返回这个对象。

如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:

classname (const classname &obj) { //传一个引用,所谓拷贝就是说不会修改原来的,只是用一个对象去初始化另一个对象
// 构造函数的主体
}

static

​ 静态方法只能访问静态变量
​ 静态成员可用类名访问::(类似python的类方法)因为它属于整个类 而不是某个对象 因此没有this
​ static变量有全局的生存期

重载运算符

1
2
3
4
5
6
7
8
9
10
11
12
 +-*/%<>!==等  30 31 32 33
用关键字 operator 修饰要重载的运算符,如
operator * (...){} //重载了*
运算符左边的变量叫reciver,决定用哪个的运算符来运算,就像取A的成员i =>A.i
如 x+y ===> x.operator+(y)
//exp1:成员函数
const String classname::operator * (const String& that){} //也可定义在类中
^返回类型&&保证不修改算子(++ -- =等不用const) ^类中(说明this->可用);

//exp2:全局函数
const String classname::operator + (const String a,const String b){}
//这个好像会自动把参数放到两边?

初始化!=赋值

1
2


explicit&implicit

​ 首先, C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的(所以不会自动调用), 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式).

左右移<< >>

模板&&泛型&&标准模板

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
// 函数模板
//template <class T> re-type func(T x,T y){} <-跟在template后,就是函数模板,T代表一个类型,就会自动根据T的类型变化
//或使用template <typename T>
//使用

int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl; //自动根据类型来

double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;

string s1 = "Hello";
string s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;

//类模板(同理

template <class T> class classname{
int T;char T;T func(){}....
}
//使用=>在实例化的时候指定类型
classname<T> a;

//标准模板 如 (标准)类模板---> vector<type>
Vector:Vector 是一个类模板。不是一种数据类型。 Vector<int>是一种数据类型。
//一、 定义和初始化
Vector<T> v1; //默认构造函数v1为空
Vector<T> v2(v1);//v2是v1的一个副本(拷贝构造?)
Vector<T> v3(n,i);//v3包含n个值为i的元素
Vector<T> v4(n); //v4含有n个值为0的元素
//二、 值初始化
//1> 如果没有指定元素初始化式,标准库自行提供一个初始化值进行值初始化。
//2> 如果保存的式含有构造函数的类类型的元素,标准库使用该类型的构造函数初始化。
//3> 如果保存的式没有构造函数的类类型的元素,标准库产生一个带初始值的对象,使用这个对象进行值初始化。
//三、Vector对象最重要的几种操作
//1. v.push_back(t) 在数组的最后添加一个值为t的数据
//2. v.size() 当前使用数据的大小
//3. v.empty() 判断vector是否为空
//4. v[n] 返回v中位置为n的元素
//5. v1=v2 把v1的元素替换为v2元素的副本
//6. v1==v2 判断v1与v2是否相等
//7. !=、<、<=、>、>= 保持这些操作符惯有含义

模板只是为编译器指出了要怎么做,并不会减少实际的代码量。编译器会根据模板的类型生成函数。

实例化和具体化

隐式实例化

编译器使用模板为特定类型生成函数定义时,的到的是模板实例(instantiation)。

在使用模板函数时,编译器会根据参数的类型自动对函数进行定义,这种实例化的方式称为 隐式实例化。如

1
2
3
4
5
6
7
8
9
10
11
12
template <typename T> void Swap(T& a, T$ b); //或者使用 <class T>

int a, b;
double c, d;

Swap(a, b);
Swap(c, d); // 根据参数实例化函数(int 或 double)
Swap(a, c); // 隐式实例化在这种情况就不行了,因为模板要求两个参数类型相同,因此需要显示实例化

template <typename T> void Swap(T& a, T$ b){
A
}

显示实例化

这意味着直接命令编译器生成特定的实例,其语法是

1
template void Swap<double>(double, double);  // 编译器看到这种声明后,使用模板生成一个double类型的实例

也可在程序中调用函数来进行显示实例化

1
cout << Swap<double>(a, c);  // 因为使用的是double类型的实例,所以上面两个参数不一致的问题的到解决,因为int可以赋值给double

具体化

具体化是具体对模板中某特定类型生成函数,具体化使用下面两个等价声明之一:

1
2
3
4
5
6
7
8
9
10
11
template <> void Swap<int>(int&, int&);
template <> void Swap(int&, int&);


template <typename T> void Swap(T& a, T$ b){
A
}

template <> void Swap(class&, class&){ // 使用具体化函数处理特定类型
B
}

异常处理

​ try catch throw(类似java 只是说明有抛出时用的是throw而不是throws)
​ 支持异常再抛出
​ catch(…)捕所有
​ 异常声明列表 void func() throw (type1,type2,type3..) 可有多个

评论