C++入门(3)

欢迎加入QQ:498903810 一起交流、讨论知识,里面有大佬,也有小白,天下码农一家亲,大家一起讨论进步。

C++ 学习路线

类与类的关系

继承

多态

文件操作

错误处理机制

  • 异常

模板(泛式编程)

STL标准库

C++进阶

动态库、静态库

重载原理(函数指针)

智能指针:vptr—>多态

day19

doxygen—>生成代码文档

你们懂我… … —> 假装这里有一个苦笑

简介

开源跨平台的注释文档生成工具。

条件

安装cmake:yum -y install cmake

安装

  1. 下载
  2. 解压tar zxvf doxygen压缩包
  3. 切换到解压后的doxygen主目录cd doxygen解压目录
  4. 创建build目录mkdir build
  5. 切换到build目录cd build
  6. 生成Linux Makefilecmake -G "Unix Makefiles" ../
  7. 编译make
  8. 安装make install

使用

  1. 进入项目目录cd 项目目录
  2. 生成配置文件doxygen –g (默认配置文件名为Doxyfile)
  3. 生成文档文件doxygen

配置文件

# 项目名称,将作为于所生成的程序文档首页标题
PROJECT_NAME        = “Test”
# 文档版本号,可对应于项目版本号,譬如 svn、cvs 所生成的项目版本号
PROJECT_NUMBER      = "1.0.0
# 程序文档输出目录
OUTPUT_DIRECTORY    =  /home/user1/docs

# 程序文档输入目录 
INPUT                = /home/user1/project/kernel

# 程序文档语言环境
OUTPUT_LANGUAGE      = Chinese
DOXYFILE_ENCODING  = UTF-8
# 只对头文件中的文档化信息生成程序文档 
FILE_PATTERNS        = 

# 递归遍历当前目录的子目录,寻找被文档化的程序源文件 
RECURSIVE            = YES 
# 如果是制作 C 程序文档,该选项必须设为 YES,否则默认生成 C++ 文档格式
OPTIMIZE_OUTPUT_FOR_C  = YES

#提取信息,包含类的私有数据成员和静态成员
EXTRACT_ALL            = yes
EXTRACT_PRIVATE        = yes
EXTRACT_STATIC        = yes
# 对于使用 typedef 定义的结构体、枚举、联合等数据类型,只按照 typedef 定义的类型名进行文档化
TYPEDEF_HIDES_STRUCT  = YES
# 在 C++ 程序文档中,该值可以设置为 NO,而在 C 程序文档中,由于 C 语言没有所谓的域/名字空间这样的概念,所以此处设置为 YES
HIDE_SCOPE_NAMES      = YES
# 让 doxygen 静悄悄地为你生成文档,只有出现警告或错误时,才在终端输出提示信息
QUIET  = YES
# 递归遍历示例程序目录的子目录,寻找被文档化的程序源文件
EXAMPLE_RECURSIVE      = YES
# 允许程序文档中显示本文档化的函数相互调用关系
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION    = YES
REFERENCES_LINK_SOURCE = YES
# 不生成 latex 格式的程序文档
GENERATE_LATEX        = NO
# 在程序文档中允许以图例形式显示函数调用关系,前提是你已经安装了 graphviz 软件包
HAVE_DOT              = YES
CALL_GRAPH            = YES
CALLER_GRAPH          = YES
#在最后生成的文档中,把所有的源代码包含在其中
SOURCE BROWSER        = YES
$这会在HTML文档中,添加一个侧边栏,并以树状结构显示包、类、接口等的关系
GENERATE TREEVIEW      = ALL

语法简介

  • 简单注释
    • 单行注释:///或者//!
    • 多行注释:/**或者/*!
  • 文件注释
/**
 * @file 文件名
 * @brief 简介
 * @details 细节
 * @mainpage 工程概览
 * @author 作者
 * @version 版本号
 * @date 年-月-日
 */
  • 全局常量/变量/宏定义/结构体定义/类定义的注释
    • 代码前注释
/// 注释
全局常量/变量/宏定义/结构体定义/类定义

例如:

/// 缓存大小
#define BUFSIZ 1024*4
  • 代码后注释
全局常量/变量/宏定义/结构体定义/类定义 ///< 注释

例如:

#define BUFSIZ 1024*4 ///< 缓存大小
  • 函数注释
/**
 * @brief 函数简介
 *
 * @param 形参 参数说明
 * @param 形参 参数说明
 * @return 返回值说明
*/

例如:

/**
 * @brief 主函数
 * @details 程序唯一入口
 *
 * @param argc 命令参数个数
 * @param argv 命令参数指针数组
 * @return @c 0 程序执行成功
 *               @c 1 程序执行失败
*/
int main(int argc, char* argv[]){
}
命令生成字段名
@param参数
@return返回值
@p参数(后面紧接单词是参数)
@c代码(后面紧接单词是代码)

* 其它常用命令

命令生成字段名说明
@attention注意
@bug缺陷链接到所有缺陷汇总的缺陷列表
@warning警告
@see参考
@code代码块开始@endcode成对使用
@endcode代码块结束@code成对使用
@todoTODO链接到所有TODO 汇总的TODO 列表

cppcheck—>静态检查代码的工具

你们懂我… … —> 假装这里有一个苦笑

简介

静态代码检查工具,支持c, c++ 代码;

  1. 自动变量检查
  2. 数组的边界检查
  3. class类检查
  4. 过期的函数,废弃函数调用检查
  5. 异常内存使用,释放检查
  6. 内存泄漏检查,主要是通过内存引用指针
  7. 操作系统资源释放检查,中断,文件描述符等
  8. 异常STL 函数使用检查
  9. 代码格式错误,以及性能因素检查

安装

  1. 下载
  2. 解压tar -zxvf cppcheck-版本号.tar.gz
  3. 进入目录cd cppcheck-版本号
  4. 编译make

使用

  • 多线程检测
cppcheck -j 线程数 --enable=检查级别  检查目录

检查级别分为all style information

运算符重载

友元函数

之前已经说过了友元函数,这里再提一下下,这里才是友元函数的主要用途。

作用:类外函数访问类内的私有属性

分类:

  • 全局友元函数:将全局函数声明成友元函数
  • 友元成员函数:类的提前引用声明,将一个函数声明为多个类的友元函数
  • 友元类:将整个类声明为友元函数

特点:

  • 友元关系单向性
  • 友元关系不可传递

友元函数重载运算符常用于运算符的左右操作数类型不同的情况。

函数重载的规则

  • 不能重载的运算符:成员运算符.、作用域运算符::sizeof、条件运算符?:
  • 不允许用户自定义新的运算符,只能对已有的运算符进行重载
  • 重载运算符不允许改变运算符原操作数的个数
  • 重载运算符不能改变运算符的优先级
  • 重载运算符函数不能有默认的参数,会导致参数个数不匹配

重载<< 和 >> 操作符

重载<<>>操作符必须使用友元函数,且形参必须为引用,因为cout,cin不允许被拷贝

#include <iostream>
#include <cstring>

using namespace std;

class String
{
public:
    String(const char * str = NULL):size(0), str(NULL)
    {
        if(NULL != str)
        {
            this->size = strlen(str);
            this->str = new char[size + 1];
            strncpy(this->str, str, this->size);
            this->str[size] = '\0';
        }
        else
        {
            this->str = new char[1];
            this->str[0] = '\0';
            size = 0;
        }
    }
    String(const String & obj)
    {
        if(NULL != obj.str)
        {
            this->str  = new char[size + 1];
            strncpy(this->str, obj.str, size);
            this->str[size];
            this->size = obj.size;
        }
    }
    String & operator=(const String & obj)
    {
        if(this != &obj)
        {
            if(this->str != NULL)
            {
                delete []this->str;
                this->str = NULL;
            }
            this->size = obj.size;
            this->str  = new char[this->size + 1];
            strncpy(this->str, obj.str, size);
            this->str[size] = '\0';
        }
        return *this;
    }
    friend ostream & operator<<(ostream &out, String &obj);
    friend istream & operator>>(istream &in, String &obj);
    ~String()
    {
        if(NULL != this->str)
            delete []str;
        this->size = 0;
    }
    void Print()
    {
            cout << str;
    }
private:
    int size;
    char * str;
};

ostream & operator<<(ostream &out, String & obj)//重载<<操作符
{
        out << obj.str;
        return out;
        //return out << obj.str;//联式编程
}
istream & operator>>(istream &in, String & obj)//重载<<操作符
{
        char tmp[1024] = {0};
        in >> tmp;
        if(*tmp != '\0')
        {
            obj.size = strlen(tmp);
            if(obj.str != NULL)//释放原来的内存空间
            {
                delete [] obj.str;
                obj.str = NULL;
            }
            obj.str = new char[obj.size + 1];//申请新的内存空间
            strncpy(obj.str, tmp, obj.size);//拷贝数据
            obj.str[obj.size] = '\0';//补尾
        }
        return in;
}

int main()
{
    String s1;
    s1.Print();
    String s("hello world");
    cout << s << endl;
    cin >> s;
    cout << s <<endl;
    return 0;
}

注:不能重载的运算符:.、 ::、 .、 ?:、 sizeof。*

只能通过成员函数进行重载操作符:=、[]、()、-> 。

重载=、+、+=、==、!=、-运算符,比较:if(10 == c)、 if(c == 10),左右操作数不同时的运算符重载

重载==运算符时,==比较时,必须是友元函数,且形参需要加const修饰符号

友元函数重载运算符常用于运算符的左右操作数类型不同的情况。

#include <iostream>

using namespace std;

class Complex
{
public:
    Complex(double real = 0, double imag = 0):real(real), imag(imag){}
    void Print()
    {
        cout << "real = " << real << "  imag = " << imag << endl;
    }
    Complex operator=(const Complex &obj);
    Complex operator+(const Complex & obj);
    Complex operator+=(const Complex & obj);
    bool operator==(const Complex & obj);//第一种
    bool operator!=(const Complex & obj);
    friend Complex operator-(Complex &ret, const Complex & obj);
    friend bool operator==(const Complex & obj,const double &i);
    friend bool operator==(const double &i, const Complex & obj);
private:
    double real;
    double imag;
};

//重载=运算符
Complex Complex::operator=(const Complex &obj)
{
    this->imag = obj.imag;
    this->real = obj.real;
    return *this;
}
//重载+运算符
Complex Complex::operator+(const Complex & obj)
{
    return (Complex(this->real + obj.real, this->imag + obj.imag));
}
//重载+=运算符
Complex Complex::operator+=(const Complex & obj)
{
    *this = *this + obj;
    return *this;
}
//重载==运算符
bool Complex::operator==(const Complex & obj)
{
    if(this->imag == obj.imag && this->real == obj.real)
        return true;
    else
        return false;
}
//重载!=运算符
bool Complex::operator!=(const Complex & obj)
{
    if(!(*this == obj))
        return true;
    else
        return false;
}
//友元重载-运算符
Complex operator-(Complex &ret, const Complex & obj)
{
    return Complex(ret.real - obj.real, ret.imag - obj.imag);
}

//第二种 --->重载==比较类型不同数据类型,用友元函数
bool operator==(const Complex & obj, const double &i)
{
    return obj.imag == 0 && obj.real == i;
}

//第三种 --->重载==比较类型不同数据类型,用友元函数
bool operator==(const double &i, const Complex & obj)
{
    return obj.real == i && obj.imag == 0;
}
int main()
{
    Complex c1(1, 2);
    Complex c2(1, 2);
    Complex c3;

    c3 = c1 + c2;
    c3.Print();
    c3 += c1;
    c3.Print();
    c3 = c3 - c1;
    c3.Print();
    if(c3 == c1)
        cout << "c3等于c1" << endl;
    else
        cout << "c3不等于c1" << endl;

    if(c1 != c2)
        cout << "c1不等于c2" << endl;
    else
        cout << "c1等于c2" << endl;

    if(c3 == 10)
        cout << "c3等于10" << endl;
    else
        cout << "c3不等于10" << endl;

    if(10 == c3)
        cout << "10等于c3" << endl;
    else
        cout << "10不等于c3" << endl;
    return 0;
}
运行结果:
real = 2  imag = 4
real = 3  imag = 6
real = 2  imag = 4
c3不等于c1
c1等于c2
c3不等于10
10不等于c3

重载 前置++、后置++、前置–、后置–

#include <iostream>

using namespace std;

class Complex
{
public:
    Complex(int real = 0, int imag = 0):real(real), imag(imag){}
    Complex operator++();//前置++,成员函数
    friend Complex operator++(Complex & obj, int);//后置++,友元函数
    Complex operator--();//前置--,成员函数
    friend Complex operator--(Complex & obj, int);//后置--,友元函数
    friend ostream & operator<<(ostream &out, Complex &obj);//重载<<运算符
private:
    int real;
    int imag;
};
//前置++,成员函数
Complex Complex::operator++()
{
    this->real++;
    this->imag++;
    return *this;
}
//后置++,友元函数
Complex operator++(Complex & obj, int)
{
    Complex tmp = obj;
    obj.real++;
    obj.imag++;
    return tmp;
}
//前置--,成员函数
Complex Complex::operator--()
{
    this->real--;
    this->imag--;
    return *this;
}
//后置--,友元函数
Complex operator--(Complex & obj, int)
{
    Complex tmp = obj;
    obj.real--;
    obj.imag--;
    return tmp;
}
//重载<<运算符
ostream & operator<<(ostream &out, Complex &obj)
{
    cout << "real = " << obj.real << "  image = " << obj.imag << endl;
    return out;
}

int main()
{
    Complex ct1;
    Complex ct2;
    Complex ct3;
    Complex ct4;

    Complex c1 = ct1--;
    Complex c2 = --ct2;
    Complex c3 = ct3++;
    Complex c4 = ++ct4;

    cout << "c1 = " << c1 << endl;//后置自减
    cout << "ct1 = " << ct1 << endl;

    cout << "c2 = " << c2 << endl;//前置自减
    cout << "ct2 = " << ct2 << endl;

    cout << "c3 = " << c3 << endl;//后置自增
    cout << "ct3 = " << ct3 << endl;

    cout << "c4 = " << c4 << endl;//前置自增
    cout << "ct4 = " << ct4 << endl;
    return 0;
}
运行结果:
c1 = real = 0  image = 0//后置自减

ct1 = real = -1  image = -1

c2 = real = -1  image = -1//前置自减

ct2 = real = -1  image = -1

c3 = real = 0  image = 0//后置自增

ct3 = real = 1  image = 1

c4 = real = 1  image = 1//前置自增

ct4 = real = 1  image = 1

继承

语法:

class 派生类:[访问限定符] 基类
{
    //成员
}
#include <iostream>
#include <cmath>

using namespace std;

class Triangle//三角形
{
public:
    Triangle(int a, int b, int c):a(a), b(b), c(c)
    {
        if(IsValidate())
            ;
        else
        {
            cout << "输入的值有错误" << endl;
            cout << "已经重置为0, 0, 0" << endl;
            a = 0;
            b = 0;
            c = 0;
        }
    }
    bool IsValidate() const
    {
        return a < c + b && c < a + b && b < a + c;
    }
    int GetTotalLength()
    {
        if(a && b && c)
        {
            return a + b + c;
        }
        else
            return 0;
    }
    double GetArea() const
    {
        if(a && b && c)
        {
            double half = (a + b + c) /  2.0;
            return sqrt((half - a) * half + (half - b) * half + (half - c) * half);
        }
        return 0;
    }
private:
    int a;
    int b;
    int c;
};

class IsoTriangle:public Triangle
{
public:
    IsoTriangle(int iso, int side):Triangle(iso, iso, side){};
private:
};
int main()
{
    Triangle t(3, 4, 5);
    cout << "周长 = " << t.GetTotalLength() << endl;
    cout << "面积 = " << t.GetArea() << endl;
    IsoTriangle iso(3,4);
    cout << "周长 = " << iso.GetTotalLength() << endl;
    cout << "面积 = " << iso.GetArea() << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值