目录
一、C vs C++,关于数据和函数
二、class分类
2.1 complex(经典不带指针--复数)
2.2 string(经典带指针--字符串)
三、Object Based(基于对象)vs Object Oriented(面向对象)
四、C++ programs代码基本形式
五、Output(输出区别),C++ vs C
六、Header(头文件)当中的防卫式声明与布局
6.1 guard(防卫式声明)
6.2 Header(头文件)的布局
6.1.1 class 的声明(declaration)
6.1.2 class template(模板)简介
在C语言中,设计程序时,需要准备数据Data与函数Functions,函数是用来处理数据,那么这个数据Data会有很多类型(built-in内置、struct结构体),Data数据根据类型创建许多真值数据variables。这样的缺点是由于语言没有提供足够的关键字,variables数据一定是全局的,对于所有Functions都可以处理variables,对后续有影响。
于是发展到了C++面向对象的语言中,将数据Date Membres与Members Function进行绑定,称为class,相当于C中的struct结构体,但是多了很多新特性,即只有对应的Members Function函数可以处理Data Members数据,优点是不会进行混杂。Data Membres与Members Function绑定后,根据这些class,以这种形式,创建了很多的objects(对象),在objects中进行处理。
在上一章中我们说,最经典的class分类为不带指针的与带指针的,这里面最经典的两个分别是complex(复数)与string(字符串)。
complex有实部与虚部之分,那么根据complex创建出来的c1、c2……中每个都含有实部与虚部,这就是在内存中占用的大小。在设计复数中还需要设计包含黄色的Functions,来处理c1、c2……,即一类函数处理多个数据。
complex中把Date与Functions包含在一起,说数据有很多个但函数只有一类,这个原因会在后面讲到。
complex c1(2,1);
complex c2;
complex* pc = new complex(0,1);
特别在于,对“Hello World”这类字符串,实际上其中只有一根指针(ptr),那么ptr要在内存中指出这个字符串,这个字符串(内容、即"Hello World")在另外设计这个类的内存中,分配空间存储这个字符串(内容)。
所以创建出来的s1、s2……,这些字符串所占用的内存大小中,实际上只有一个ptr。
string s1("Hello");
string s2("World");
string* ps = new string;
代码中创建方式是不同的,后续会说到
Object Based:面对的是单一class的设计
omplex(复数)--Class without pointer member(s))
Object Oriented:面对的是多重classes的设计,classes和classes之间的联系。
string(字符串)--Class with pointer member(s)
在一个C++ programs中,包含一个头文件、主程序、标准库(当然这么分并不是很准确但可以这里理解)。
主程序使用头文件,使用include"---",使用标准库,使用include<--->。头文件和标准库都为.h文件,对声明和标准库的区别就是双引号和尖括号的区别。
对于文件名,或者说延伸的文件名(extension file name)可能不会是.h / .cpp的后缀,可能是.hpp或其他的,甚至无延伸的文件名。
在C 中使用#include
#include
int main()
{
int i = 7;
printf("i=%d \n" , i);
return 0;
}
在C++中有更好的方法,#include
#include
using namespace std;
int main()
{
int i = 7;
cout << "i=" << i << endl;
return 0;
}
对complex.h中,有严格的头文件写法,我们说很多程序要用到这个声明文件,或者说自己用到,那么include中为了忽略次序引用,所以说写一个guard(防卫式声明)。第二次进行include时不会做多余的动作。
(程序内容不做详细说明,只说COMPLEX是自己定义的)
#ifndef __COMPLEX__
#difine __COMPLEX__
------------------
- -
- -
- -
-······ -
- -
- -
------------------
#endif
那么在下列的以complex-test.h中,实际上对复数进行的操作,就是中间主体部分,即“--------”之间的内容。
#include
#include "complex.h"
using namespace std;
int main()
{
complex c1(2,1);
complex c2;
cout << c1 << endl;
cout << c2 << endl;
c2 = c1 + 5;
c2 = 7 + c1;
c2 = c1 + c2;
.......
return 0;
}
在一个基本的complex.h中,具体是以下布局
其中开始的第一段“--------”到“-----------”为forward declarations(前置声明)
第二段中为class declarations(类-声明)重要
第三段中为class definition(类-定义)重要
#ifndef __COMPLEX__
#difine __COMPLEX__
----------------------------------------------------
#include
class ostream;
class complex;
complex&
__doapl (complex* ths, const complex& r);
---------------------------------------------------
---------------------------------------------------
class complex
{
.......
};
---------------------------------------------------
---------------------------------------------------
complex::function...
---------------------------------------------------
#endif
class complex
{
public:
explicit 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都有class hand,在下方中第一个“ { } ”中为class body。在class body中设计complex应该是什么样的数据,是怎么样的函数,来满足使用要求。
private:
double re , im;
这里是Data,上面就是就是Data的函数,后续讲到。friend为在设计另一类、单元、函数与现在的关系。
在复数中最重要的是里面该有什么样的信息,即有实部与虚部,代码中为double re , im;
即实部re,虚部im都为double值,假如设计为浮点数,整数,那么需要再写一个class complex 将private:部分的double改为float/int,其余同理,只是类型不同而已。所以这里引出一个模板。
这里我们不将数据实部虚部类型写死,而是T(只是一个符号)类,告诉编译器,类型未定,则第一行写template
template
class complex
{
public:
explicit 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:
T re , im;
friend complex& __doapl (complex* , const complex&);
};
那么使用的时候再指定,写法如下:
{
complex c1(2.5 , 1.5);
complex c2(2 , 6);
……
}
但我们在后续写的时候依旧不会用到模板。
下一章:(三)C++构造函数