C++知识点

侯捷老师-C++课件_面向对象高级编程:链接

什么是深复制?什么是浅复制?(深拷贝与浅拷贝)

参考链接:深拷贝与浅拷贝

经典分类   

  1. 不带指针的类(complex)
  2. 带指针的类(string)

    头文件中的防卫式声明   

    1
    2
    3
    4
    5
    6
    #ifndef __COMPLEX__
    #define __COMPLEX__

    ..........

    #endif

模板(class template)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template<typename T>
class complex
{
public:
complex (T r = 0, T i = 0) : re(r), im(i) { }
complex& operator += (const complex&);
T real () const { return re; }
T imag () const { return im; }
private:
T re, im;

friend complex& __doapl (complex*, const complex&);
};


{
complex<double> c1(2.5, 1.5);
complex<int> c2(2, 6);
}

内联函数(inline)

函数在类本体内定义则是内联函数,否则不是。所有函数都可以写成inline,但有些函数定义为inline,但是编译器没有能力将他做成inline。(函数过于复杂则不能)

访问级别   

private层变量只能class本体成员函数访问。

构造函数

  • 创建一个对象时候,一个函数会自动调用起来,这个函数就是构造函数。
  • 构造函数没有返回值。
  • 构造函数可以有默认值。
  • 初始化参数:仅构造函数才享有。   

    构造函数有两个阶段:

  1. 初始化阶段。(这就是初始化参数的效果,如果不那样做,就等于放弃了初始化阶段,从而效率变差。)
  2. 赋值阶段。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class complex
    {
    public:
    complex (double r = 0, double i = 0) : re (r), im (i) { } //初始化参数 
    /*
    相当于 complex (double r = 0, double i = 0) { re = r; im = i; }
    */
    complex& operator += (const complex&);
    double real () const { return re; }
    double imag () const { return im; }
    private:
    double re, im;

    friend complex& __doapl (complex*, const complex&);
    };

    {
    complex c1(2, 1);
    complex c2;
    complex* p = new complex(4);
    ...
    }

构造函数可以有很多个-overloading(重载)

1
2
double real () const { return re; }
void real (double r) { re = r; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class complex
{
public:
complex (double r = 0, double i = 0) : re (r), im (i) { } //初始化参数 
complex () : re(0), im(0) { } //这种写法不行,会使得编译器犹豫不知道选择哪一个
/*
complex c1;
complex c2();
*/
complex& operator += (const complex&);
double real () const { return re; }
double imag () const { return im; }
private:
double re, im;

friend complex& __doapl (complex*, const complex&);
};

构造函数放在private区

singleton:外部只有一个接口访问这个类,单例模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A {
public:
static A& getInstance();
setup() { ... }
private:
A();
A(const A& rhs);
...
};

A& A::getInstance() {
static A a;
return a;
};

调用时候,不能用传统方式A a(); 只能用A::getInstance().setup();

常量成员函数(const member functions)

函数分为内部改变数据的与内部不会改变数据的。不会改变数据的则最好使用const。

1
2
double real() const { return re; }
double imag() const { return im; }

函数该加const时候不加const的后果

这样调用是ok 的。

1
2
3
4
5
{
complex c1(2, 1);
cout << c1.real();
cout << c1.imag();
}

下面这种情况不加,当c1.real()执行时,real()函数后面没有加const,此时,c1.real()语句是const,不能更改,然后real()函数会发生更改,所以会导致编译器错误。

1
2
3
4
5
{
const complex c1(2, 1);
cout << c1.real();
cout << c1.imag();
}

参数传递:pass by value vs. pass by reference(to const)

值传递:整个包都会传递过去,效率较差。

尽量所有参数都传引用。

传递速度很快,且不能更改:则pass by reference to const。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class complex
{
public:
complex (double r = 0, double i = 0) : re (r), im (i) { } //初始化参数 
/*
相当于 complex (double r = 0, double i = 0) { re = r; im = i; }
*/
complex& operator += (const complex&);
double real () const { return re; }
double imag () const { return im; }
private:
double re, im;

friend complex& __doapl (complex*, const complex&);
};

返回值传递:return by value vs. return by reference(to const)

1
2
3
ostream& operator << (ostream& os, const complex& x) {
return os << '(' << real(x) << ',' << imag(x) << ')';
}

友元(friend)

友元函数是可以直接访问类的私有成员的非成员函数。 它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend。

参考链接:友元

1
2
3
4
5
inline complex& __doapl(complex* ths, const complex& r) {
ths->re += r.re; //自由取得friend的private成员
ths->im += r.im;
return *ths;
}

相同class 的各个objects互为friends(友元)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class complex {
public:
complex (double r = 0, double i = 0) : re (r), im (i) { }

int func(const complex& param) { //完美解释
return param.re + param.im;
}
private:
double re, im;
};


{
complex c1(2, 1);
complex c2;
c2.func(c1);
}

操作符重载-1, 成员函数,this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
inline complex& __doapl(complex* ths, const complex& r) {
ths->re += r.re;
ths->im += r.im;
return *ths;
}

inline complex& complex::operator += (const complex& r) {
return __doapl (this, r);
}

{
complex c1(2, 1);
complex c2(5);

c2 += c1;
}

====>>>//所有成员函数都带有一个隐藏的this 指针
inline complex& complex::operator += (this, const complex& r) {
return __doapl (this, r);
}

return by reference 语法分析

传递着无需知道接受者是以reference形式接收

1
2
3
4
5
6
7
8
9
inline complex& __doapl(complex* ths, const complex& r) {
ths->re += r.re;
ths->im += r.im;
return *ths;
}

inline complex& complex::operator += (const complex& r) {
return __doapl (this, r);
}

操作符重载-2,非成员函数(无this)

image
image
image
image
image
image

类里面带着指针

image

1
2
string s3(s1); 	//拷贝构造
string s3 = s2; //拷贝赋值

image

1
2
3
4
5
	String(const String& str); 	//拷贝构造
String& operator=(const String& str); //拷贝赋值
private:
...
char* m_data; //最好写成动态形式

image

1
delete[] m_data; 	//析构清理

image

会导致内存泄露,制造野指针,变成孤儿(浅拷贝)。

image

深拷贝

image

三步:1、先分配空间。2、重新创造自己。3、拷贝过来。
必须要进行检测自我赋值。如果相同时候结果会出错,将原地址也清空了。

image

image

image

image

image

image

stack自动释放,而heap必须手动释放。

image

image

静态,作用域结束之后仍然存在。

image

全局作用域。

image

image

new分为三个动作:1、分配内存。2、转型。3、构造函数。

image

delete两个动作:1、析构函数。2、delete.

image

image

image

image

image

image

image

image

image

image

==>>后面是以c的调用。相同的函数传递的是不同的地址。成员函数有一个隐藏的this指针,可以在函数中去使用它,在参数列中不可以写。加上static后不属于某一个对象,只有一份。静态函数没有this指针,指针去存取静态数据,不能像一般成员函数那样存取一般数据成员。

image

静态数据一定要在类的外部设置初值(定义)。 静态函数只能处理静态数据。两种调用方式:类调用、对象调用。

image

这个才是更好的写法。有调用a 才会出现,使得资源不浪费。

image

生成的class只想产生一个对象。这里的A只有一份,设置静态函数使得与外界联系的唯一接口。这里如果没有创建a,则会浪费资源。

image

image

模板写法。T 只是一个符号而已。

image

编译器会对函数模板进行参数推到。<操作符重载。

image

所有东西被包装一个namespace里面,防止自己写的与其他人写的重名。也可以不一下全部打开,一条一条的打开。

image

image

image

image

里面有另外一个东西。queue里面有一个deque。A has a B,A的功能让B去完成。
Adapter设计模式。queue是一个Adapter.

image

image

构造由内而外,析构由外而内。

image

image

image

父类的析构函数必须是virtual.

image

纯虚函数:子类一定要去重新定义他,父类并没有去定义。这也是一种设计模式。

image

image

image

image

既有继承,又有复合,构造时候谁先?

image

image

image

image

image

image

image

image

image