软件设计II模板整理_C++面向对象编程

原创 2016年05月30日 13:30:52

6.11更新

因为没有人来cording hub..所以丢回github了
顺便搭了一个博客更新放在这了

6.2已经更新

整理了原来乱七八糟的框架结构
删除了参考模板
模拟考试前会更新~
考试前会出便于打印版本~

这是一个开源项目

希望懂一点点git和markdown的同学能参与进来

  • 因为coding是中文网站,界面比较友好便放在那里了
    和github使用对比只是没有命令行操作吧..
    其实主要就是上传/修改文件到分支

markdown学习笔记
git参考教程

项目地址

点进去下载w

在这个地址里面的版本较新,完成较好后或会整理便于打印的版本

软件设计II模板

leidar100@gmail.com

  • 类函数的实现implementation

    有些题目往往给出了类的声明,要求完成实现.其实也就是在类外写一个函数

    函数名前面加上类名

    class seriesComp{
        seriesComp(int n);
        int sum();
    }
    //返回类型不用改变,参数名不用改变,只要在函数名前加类名
    seriesComp::seriesComp(int n)
    {
    // your code
    }//构造就不用返回
    int seriesComp::sum() {
    // your code
    }//该返回int就返回int
    //和上面等价的实现
    class seriesComp{
        seriesComp(int n){
        // your code1
    }
        int sum(){
        // your code2
    }
    }

构造函数

  • 初始化成员变量

    1. this指针

      //常见于构造函数,区分与传入参量的相同名字
      Date::Date(int year, int month)
      {
       this->year =year;           //可调用属性
      this->month=month;
       this->pass =this->validate();//可调用方法
      }
    2. 成员初始化器

      //在构造函数里面,即使和传入名相同(同上)
      Date::Date(int year, int month)
      :year(year),month(month)     //用逗号分开
      {
       this->pass =this->validate();//可调用方法
      }
    3. 对于指针分配新的内存空间=>数组

      //new char[长度]  char可以换成别的类型或者模板T
      
    4. 更新static计数器数目

    5. 调用Setter更新

  • 拷贝构造函数

    1. 关键在于加&传引用*,不然会无限递归

    2. 深拷贝(当传入一个数组时候需要考虑,直接赋值仅仅改变了指针方向)

      String::String(const String& b){
       str=new char[strlen(b.str)+1];//#include <cstring>,动态分配内存空间
       int pos;
       for (pos=0; b.str[pos]!='\0'; pos++) 
           str[pos]=b.str[pos];
       str[pos]='\0';//字符串最后一位记得加'\0'
      }

析构函数(RAII)

  • 长相

    • 没有返回值,没有参数
    • 函数名前加~:ClassName
  • 清理动态(new)分配的内存空间

  • 可能与static参量相关,析构时候-1

    MyString::~MyString(){
      MyString::numberOfObjects--;//如果有计数器的话
      delete str;//删除没有被分配空间的指针时候会CE
    }

  • 在出了代码块或者使用delete时候调用

Getter & Setter

  • 为了实现类的封装(从外界装逼地修改private数据),于是出现了Getter个setter

    这样就可以象征性的保护类中的数据和方法

  • Getter模板

    int Date::getYear() const
    {
      return year;//一般直接返回,但是在重载数组[]的时候如果认为是getter可能检查下标
    }
  • Setter模板

    与Getter不同的是,往往需要检查传入数据的合法性

    void Date::setDate(const string& input)
    {
      if (checkFormat(input))
      {
          istringstream trans(input);
          char temp;
          trans >> year >> temp >> month >> temp >> day;
      }//检查数据合法性
        else
          year=month=day=233;
      pass=validate();
    }

运算符重载

  1. 其实就是把函数名换成了运算符
  2. 一般而言会遵循使用习惯返回值,比如+=返回当前对象,==返回bool值
  3. +=+, ==!=都需要分开重载,+,-是重载正负运算符
  4. 很多STL使用需要重载<运算符,比如set,map,优先队列

    • 普通运算符重载(参考lab06)
    返回类型 运算符operator(符号名) (参数列表)
    {
    函数体  
    }
    /*hw05
    返回类型:Complex对象
    符号名:+
    因为是对类的方法的实现,所以要加作用域符号Complex::
    参数列表: 另一个Complex
    */
    Complex Complex::operator+(Complex&com)
    {
      Complex ans(real+com.real,imag+com.imag);
      return ans;
    }
    • 流(左移右移运算符)重载记得加&

    可参考这篇题解更深入理解<<运算符的重载

    因为是在外界调用,需要声明为友元函数

    //一般输入输出流的重载
    //按照自己意愿输出,使用和cin,cout类似
    ostream& operator<<(ostream& os, Complex& com){
      //这里给os输出一些东西 os << something
      return os;//返回流
    }
    
    //overload `>>` operator按照自己意愿输入
    istream& operator>>(istream& os, Complex& com){
      os>>com.real>>com.imag;
      return os;//返回流
    }
    • 取位运算符重载
    /*
    返回类型: double
    符号名 :  [] //重载这个运算符往往要注意位置是否合法
    参数列表: int
    */
    double& Complex::operator[](int i){
      if (i==0) {
          return real;
      }else
          return imag;
    }
    • 赋值运算符重载(或涉及深拷贝)
    /*
    返回类型: 类的对象,这里是String
    符号名 :  =  //重载这个运算符往往要注意位置是否合法
    参数列表: 任意参数,这里是char,也可以是string
    */
    String& String::operator=(const char *b){
      str=new char[strlen(b)+1];
      int pos;
      for (pos=0; b[pos]!='\0'; pos++) 
          str[pos]=b[pos];
      str[pos]='\0';
      return *this;
    }
    /*判断是否为当前,lab07*/
    const MyVector & MyVector::operator=(const MyVector &vec){
    if(*this==vec)return *this;
        delete []elem;
      int len = vec._size;
      elem = new Elements[len];
      for (int i=0; i<len; i++) 
          elem[i]=vec.elem[i];
      _size=len;
      return *this;
    };//assignment
    
    • ++ --
    // Define function operators for prefix ++ and --
    Rational& Rational::operator++(){
      numerator += denominator;
      return *this;//前缀++,可以直接把当前加一,然后返回当前
    }
    
    // Define function operators for postfix ++ and --
    
    Rational Rational::operator++(int dummy){
      Rational old = *this;
      numerator += denominator;
      return old;//后缀++,记得有dummy值,返回以前的值
    }

    • 类型转换运算符
    Rational::operator double(){
    return ((double)numerator/denominator);
    }//没有标明返回值但是需要返回

static

其实我觉得static就是类里面的“全局变量”,类中static函数+static变量相当于在面向过程的普通函数+全局变量 -by第三周实验报告

  • static成员变量需要在类外面初始化为0(lab05)

    //内部-模板
    class MyString
    {
    public:
    ...
        static int getNumberOfObjects();
    private:
    ...
      static int numberOfObjects;             //counter    
    };
    //外部-格式:类型 类名::变量名=初始值;
    int MyString::numberOfObjects=0;//necessary declare but '=0' not necessary
    
    int MyString::getNumberOfObjects(){
    return numberOfObjects;
    }//照样要加MyString::也就是类名

  • 不能被this指代

    • 应用 对象数目统计
    //构造函数+1
    MyString::MyString(int Length, char sym)
    {
        numberOfObjects++;//这里
        str = new char[Length+1];
        fill(str, str+Length, sym);//fill is an interestiong function
        str[Length]='\0';
    }
    //析构函数-1
    MyString::~MyString(){
        MyString::numberOfObjects--;
        delete str;
    }

两个类的has关系

  • 其实c++中int也是一个类,char也是一个类,只不过是语言自带的
  • 所以包含int a;和包含MyClass a层次上面是等价的..所以包含就行(见lab5)

两个类的is关系(继承)

  • 基本模型

    //在头文件中include父类的头文件
    class derived:father{
    //它的新方法和属性
    }
  • 这样就可以

    1. 拥有父类的所有东西
    2. 使用父类publicprotected可见度的方法
    3. 被父类指针指向
  • virtual 函数

    • 在父类里面函数前加virtual,子类里面实现
    • 指向子类的指针就会使用子类里面的实现
    • 纯虚构函数
    • virtual 返回值 函数名(参数列表) = 0;
    • 必须在子类实现,没有父类对象
    • virtual void withdraw(double) = 0;
    • 一般析构函数都声明为virtual

其它内容

文件流

这篇博客是一个文件流OJ的入门

  • 就是创造一个类似于cin,cout的东西
//输入流_1
#include <fstream>
ifstream fin("in.txt");
fin.close();
//输入流_2
#include <fstream>
ifstream fin;
fin.open("in.txt");
fin.close();
//另外读入string文件名的话可以用.c_str()转化为字符串
//输出流
#include <ofstream>
ofstream fout("out.txt");
fout.close();
  • 另外想舒服正常一些操作的话有下面两种方法

    1. 不include\ 起名为cin,cout

    2. 重定向流输入输出

      
      #include <cstdio>
      
      freopen("telecow.in", "r", stdin);
      freopen("telecow.out", "w", stdout); 
  • 其它流运算符hex, fixed(保留小数),showpoint,setprecision(n)

  • 流标志符eof()

sstream

  • 流对象,stringstream str(Str);
  • 可以使用>>,<<来往这个流内输入输出

模板类/函数

在函数/类前面加上

template <typename T, int capacity>//第二个是容量参数,可以用来声明数组长度

或者

template <class T>

  • 构造函数(举个例子)

    template <typename T, int capacity> //类前需要加上
    class Stack
    {
    public:
      Stack();                   // Constructs an empty stack.
    private:
      T* elements;                  // Points to an array that stores elements in the stack.
    };
    template <typename T, int capacity>   //每一个函数前都得加上
    Stack<T,capacity>::Stack()
    {
      elements = new T[capacity];
    }                   // Constructs an empty stack.
  • 使用的时候参考STL中vector使用

  • 另外这个的头文件和实现不能分成两个文件

  • 模板测试函数

    template <class T>
    void TEST(Array<T,MAXLEN> &theArray,
            T FirstValue,T increment)
    {}

异常

在一段可能除0,可能越界,可能干坏事的代码块前加上try

出现坏事throw一个对象

catch根据对象类别 选择措施

//基本模型
template <typename T, int capacity>
T& Array<T,capacity>::operator[] (int index)
{
    try {
        if (index < 0 || index >= num)
        {
            throw ArrayException("Out of Range Exception");
        }//illegal index
    }
    catch (int a){};
    return elements[index];
}
  • 异常类模板
//异常类就是专门一个类,throw这个类的一个对象
class ArrayException
{

public:

    ArrayException(const char *msg);

    const char *what() const;//约定俗成的名字

private:

    const char *message;

};

lab04

对象数组 就是对于数组指针和移位的练习,有趣的是迭代器不能+1来实现指针的移位

  • RAII

    析构了一个值之后又要重新使用那个值

    于是就拿另一个指针来存那个值

    while (cin >> value)
    {
    //下面就是一个代码块{}包围
                 {//类中把value值赋成另一个
                        AutoReset auto_reset(&value, count);
                        value *= 2;
                        count++;
                        cout << value << " ";
                 }//类作用的有效区域,出了之后需要把value值还原
     cout << value << endl;
    }
    
    int save,*s;
    AutoReset::AutoReset(int *scoped_variable, int new_value){
      s=scoped_variable;//传入的是指针,把原来指向那个值的指针存下来
      save=*scoped_variable;
      *scoped_variable=new_value;
    }
    // your code will be here
    
    AutoReset::~AutoReset(){
      *s=save;//把存下了的指针还回去
    }      

参考模板

可能用到的函数库

这一篇的最下面总结了模板头文件..

sicily上可以用#include<bits/stdc++.h>来囊括所有函数库

另外附加了三个cplusplus的网页集合

谈谈8年C++面向对象设计的经验体会

六年前,我刚热恋“面向对象”(Object-Oriented)时,一口气记住了近十个定义。六年后,我从几十万行程序中滚爬出来准备写点心得体会时,却无法解释什么是“面向对象”,就象说不清楚什么是数学那样...
  • sinat_20265495
  • sinat_20265495
  • 2016年07月23日 14:46
  • 1677

C++笔记:面向对象编程基础

面向对象编程基础 面向对象编程基于三个基本概念: 数据抽象-继承-动态绑定...
  • liufei_learning
  • liufei_learning
  • 2014年03月18日 06:20
  • 5926

C++面向对象程序设计思想(精)

C++面向对象程序设计     六年前,我刚热恋''面向对象''(Object-Oriented)时,一口气记住了近十个定义。六年后,我从几十万行程序中滚爬出来准备写点心得体会时,却无法解释什么是'...
  • qq_37018433
  • qq_37018433
  • 2017年01月20日 15:00
  • 866

C++ 软件设计思想

一,如何设计出优秀的软件系统? 优秀的软件系统,必须是易扩展、易维护、高可复用性的。要做出这样的系统,就要采用面向对象的设计思想。如果我们的设计仅仅符合面向对象的三大特征,这并不是很好的面向对象的软...
  • cloud323
  • cloud323
  • 2017年08月14日 16:53
  • 175

C++模板整理

模板(Template)指C++程序设计设计语言中采用类型作为参数的程序设计,支持通用程序设计,统一管理函数或者类。C++ 的标准库提供许多有用的函数大多结合了模板的观念,如STL以及IO Strea...
  • steft
  • steft
  • 2017年03月15日 11:13
  • 74

C++面向对象编程入门:类(class)

我们在c语言中创建一个结构体我们使用如下方法:struct  test  {      private :          int  number;      public ...
  • lucky__jin
  • lucky__jin
  • 2011年03月08日 11:01
  • 459

C++面向对象编程的基本概念及四种机制及类和对象

①面向对象编程的基本概念 1.对象——实体 组成部分:{属性,行为}。 eg.一个学生可以是一个对象,那么这个学生的属性有学号,年级,班级等;行为有选课,考试,体侧等。 2.类——抽象 组成部分:{属...
  • qq_37385726
  • qq_37385726
  • 2017年04月28日 16:36
  • 185

C++笔记: 面向对象编程进阶

[前篇]C++笔记:面向对象编程基础 转换与继承 派生类到基类到自动转换 派生类指针 ----> 基类指针 --/-> 派生类指针 派生类对象 --/-> 基类对象 --/-> 派生类...
  • liufei_learning
  • liufei_learning
  • 2014年03月28日 06:49
  • 5703

常用C++函数模板整理

1:数值交换       template static inline void swap(T& x, T& y) { T t=x; x=y; y=t; }
  • libin88211
  • libin88211
  • 2015年01月17日 15:51
  • 370

PKU C++程序设计实习 学习笔记5 文件操作和模板

第七章 文件操作和模板 7.1 文件操作 7.2 函数模板 泛型程序设计(Generic Programming) 算法实现时不指定具体要操作的数据的类型 泛型——算法实现一遍,适用于...
  • buxizhizhou530
  • buxizhizhou530
  • 2015年05月06日 23:08
  • 871
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:软件设计II模板整理_C++面向对象编程
举报原因:
原因补充:

(最多只允许输入30个字)