C++关于数据和函数
C++关于数据和函数
C语言在设计程序的时候会准备一些数据和函数,函数用来处理你创造的数据,这样会有一些缺点,由于语言没有提供足够的关键字,所以这些数据一定是全局的,所以所有的函数都可以处理这些数据,在后期会造成很大的影响的,所以面向对象语言C++出现了,基本思想是把数据和处理这些数据的函数包装在一起,也就是“类”,类其实和结构体是差不多的。
类是否涉及指针,一定要特别注意
Class 的 两个经典分类:
·Class without pointer member(s)
·Class with pointer member(s)
C++ program 代码基本形式
.h 头文件 与 .cpp 代码程序
用#include的方法使用头文件,标准库也是类似。
使用自己的写的头文件使用双引号"",默认库使用尖括号<>
延伸文件名不一定是.h或.cpp
也可能是.hpp甚至是无延伸名
在不同的平台上可能不同。
Header头文件中的防卫式声明
#ifndef _XXX_ //if not define 如果没有被定义(引用)过
#define _XXX_ //则执行下列代码直到#endif
...
...
#endif //若第一行判定被定义过,则直接跳到#endif
作用是避免多重调用,出现重定义错误!
比如 我在 Main.cpp 中
#include"op1.h" #include"op2.h" ... ... ...
而在op2.h中
#include"op1.h" ... ... ...
这样就形成了多重调用,因为op2.h中包含了op1.h,而在Main.cpp中既调用了op2.h也调用了op1.h。
所以要养成写任何一个头文件都要使用#ifndef来避免重定义的习惯。
既然有 #ifndef ,所以也有#ifdef
当在不同平台下编写代码时,由于环境不同,所以要使用的头文件也会不同,这时就可以用到#ifdef
#ifdef OS_Win #include <windows.h> #endif #ifdef OS_Linux #include <linux.h> #endif
这样就实现了windows环境下调用windows.h 而Linux环境下则调用linux.h。
Class 的声明(拿complex来举例):
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; };
public: 下的函数或者数据都是可以直接给外界访问的,而private:下的函数或数据只能内部访问。实现数据与函数封装。
class template(模板)
当你使用大量同一种数据类型的变量的时候,突然想改变这些变量的数据类型,那么一条一条代码去改是很难实现的,就比如上面有变量re和im,我想同时改变它们两个的数据类型,首先是变量声明那改成另一种数据类型,但是还有相关函数呢,返回的也是double类型,也需要更改,而且构造函数中传入的参数也是double类型,几乎所有地方都要修改,这样就显得极其麻烦,而且如果想通过不同的情况随时更改无法实现,灵活性也极差。
那么就使用到了“模板”
template<typename T> class complex { public: complex (T r = 0 , T = 0 ) //构造函数 : re(r),im(i) {} complex& operator += (const complex&); //重载+= T real() const{return re;} T imag() const{return im;} private: T re; T im; };
...主函数... { complex<double> c1(2.5,1.5); complex<int> c1(1,2); ... }
这样就想使用double类型就用double模板,使用int类型就用int模板。灵活性强。
---------------------------------------------------------------------------------------------------------
关于 避免头文件重定义的补充:
我们已经知道一种方法 #ifndef
还有一种方法是 #pragma once
那么这两种方法有什么区别呢?
#ifndef 因为要定义宏名,如果出现两个头文件定义的宏名相同的话,可能会导致使用该头文件,但编译器找不到。
#pragma once则由编译器提供保证:同一个文件不会被包含多次。且这个文件是物理上的文件,缺点是如果物理文件被拷贝多次会导致无法避免重定义,且不支持跨平台。
所以两种方法的使用需要根据情况来把握。