【C++侯捷】面向高级对象编程(一)
面向对象高级编程(一)
头文件与类的声明
一些需要注意的点
#include <iostream>
#include "complex.h"
包含的库的文件用<>
,包含用户自己建立的文件用""
,延伸文件名不一定是.h或.cpp,也有可能是 .hpp或其他或甚至无延伸名。
Header(头文件)中的防卫式声明
例如complex.h
#ifndef __COMPLEX__
#define __COMPLEX__
...
#endif
说明:当第一次引用complex文件时,会定义COMPLEX, 再当以后引入时不会再重复引用下面的
Header(头文件)的布局
#ifndef __COMPLEX__
#define __COMPLEX__
#include <cmath>
class ostream;
class complex;
complex&
__doapl (complex* this, const complex& r);
--- 前置声明
class complex
{
...
};
--- 类声明
complex::function...
--- 类定义
Class的声明
class complex{
public:
...
private:
...
};
class template(模板)简介
template<typename T>
class complex
{
public:
...
private:
...
T re,im; # T为待定的类型
};
inline(内联)函数
如果函数再class本体中定义,则称之为inline函数。优点是,总的来说,很好、很快。
但是有些函数即使你把他定义为内联函数,编译器也不会把他看成内联函数。
access level(访问级别)
public
private
protect
构造函数
示例
class complex
{
public:
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(double r = 0, double i = 0)
{re = r; im = i;}
但是要求按上述写,应该利用构造函数的这个特性。
overloading(重载)
例,与上述同名的real
,其可通过\(参数个数、类型,返回值\)类型等区分。
void real(double r) {re = r;}
但是,
complex(double r = 0, double i = 0)
:re(r), im(i)
{ }
与
complex() : re(0), im(0){}
\[不能同时出现$$;
实例化例子
```C++
{
complex c1;
complex c2();
...
}
```
将出现问题。
### 放在private区
构造函数放在private区将不能外界被创建对象。
示例
```c++
class A {
public:
static A& getInstance(); //Singleton --单体,单件的意思
setup(){...}
private:
A();
A(const A& rhs);
...
};
A& A::getInstance()
{
static A a;
return al
}
```
> 只有一份A,不允许外界创建。
>
> 外界要使用A ,不能使用传统的创建方式,可以采用以下方式
>
> ```C++
> A::getInstance().setup();
> ```
## const常用成员函数
```c++
class complex
{
public:
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&);
};
```
> Class中的函数分为可以改变数据内容和不能改变数据内容的,不会改变 数据内容的马上加上``const``。
>
> 可以加的话一定加。
两个例子
```C++
//加的话
{
complex c1(2,1);
cout << c1.real();
cout << c1.imag();
}//是没有问题的
//假如不加,但是使用者这样定义常量
{
const complex c1(2,1); //定义一个常量
cout << c1.real();
cout << c1.imag();
}
```
> 上述情况(即定义时不加const, 但是使用者在定义时加了const),意思是我在定义时表明变量数据会改变,但是使用者加const指出这个值不能改变,这样将产生冲突。编译器会发出一些信息。
## 参数传递:pass by value vs. pass by reference(to const)
<img src="https://imghome-1302941983.cos.ap-beijing.myqcloud.com/img/202210141731778.webp" alt="image-20221014173114619" style="zoom: 67%;" />
尽量不要使用pass by value, 像传包一样把整体传过去。``by reference``,传递地址。
```C++
{
complex c1(2,1);
complex c2;
c2 += c1;
cout << c2;
}
```
## 返回值传递
> return by value vs. return by reference(to const)
如果可以的话, 返回值传递也尽量``by reference``。
```C++
class complex
{
public:
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&);
};
```
## 友元
```C++
inline complex&
__doapl (complex* ths, const complex&r)
{
ths-> re += r.re;
ths-> im += r.im;
return *ths;
}
```
### 相同class的各个objects互为友元(friend)
```C++
class complex
{
public:
xxx
int func(const complex& param)
{ return param.re + param.im;}
private:
double re, im;
}
```
> 知道为什么
## class body 外的各种定义(definitions)
>探讨什么情况下可以``pass by reference`
>
>什么情况下可以``return by reference``
<img src="https://imghome-1302941983.cos.ap-beijing.myqcloud.com/img/202210171718953.webp" alt="image-20221017171759989" style="zoom:67%;" />
**return**
- 假如产生结果需要存储在函数内部新开辟的local变量里,则不可以,因为离开函数区变量将销毁;
- 若生成结果是对已有变量(内存空间)进行修改,则可以,如上图。
参数的传递或返回值的传递首先考虑引用(reference),然后再考虑有没有问题。
## Summary
**对于一个class**
- 数据一定封装在private里
- 参数尽可能是``pass by reference``
- 返回时也尽量``pass by reference``
- 类的本体能加const就加const
- 默认构造函数的实现\]