C++注意点

Protege本体建模实战:从零构建电影知识图谱并导入Neo4j 本体建模是知识图谱构建的基石,通过类、属性、实例和约束系统描述领域知识,为数据提供可复用的语义骨架。OWL作为本体描述语言的标准,配合Protege工具可实现可视化建模,并借助推理机验证逻辑一致性,提升模型可靠性。在工程落地中,本体模型常需导入图数据库如Neo4j,以支持高效的关联查询与业务应用。本文以影视领域为背景,完整演示Protege中定义类层级、创建对象/数据属性、填充实例,以及导出OWL文件并通过Python脚本转换为Neo4j节点与关系的全过程,同时梳理命名空间、匿名节点、编码等易踩坑点,帮助读 阅读详情

一   编程设计
     1.将程序划分为多个子系统,包括子系统间的接口和依赖关系、子系统间的数据流、在各子系统间的来回输入输出、以及总的线程模型。

     2.各个子系统的具体细节,包括进一步细分的类、类层次体系、数据结构、算法、特定的线程模型和错误处理。

二   设计流程
     1.需求:功能需求和性能需求。
     2.设计步骤
       (1)把程序划分为通用功能子系统,并明确子系统的接口和交互。
       (2)把这些子系统列在一个表中,并表示出子系统的高层行为或功能、子系统向其它子系统提供的接口,及此子系统使用了其他子系统的哪些接口。
       (3)选择线程模型:确定使用多少个线程,明确线程的交互并为共享数据指定加锁机制。
       (4)为每个子系统指定层次体系
       (5)为每个子系统指定类、数据结构、算法和模式
       (6)为每个子系统指定错误处理(系统错误 + 用户错误),指定是否使用异常

三   C++ 的设计原则
     1.抽象:将接口与实现相分离
     2.重用:代码重用和思想重用

四   对象关系
     1.has-a 关系(聚集)
     2.is-a  关系(继承)
     3.组织对象层次体系:
      (1)将类按有意义的功能加以组织。
      (2)将共同的功能放到超类中,从而支持代码重用。
      (3)避免子类过多的覆盖父类的功能。

五   重用设计
     1.建立可重用的代码结构
      (1)避免将无关或逻辑上分离的概念混在一起
      (2)把程序划分为子系统
      (3)使用类层次体系来分离逻辑概念
      (4)使用聚集来分离逻辑概念
      (5)对通用数据结构和算法使用模板
      (6)提供适当的检查和防护

六   设计易于使用的接口
     1.开发直观的接口
     2.不要遗漏必要的功能
     3.提供简洁的接口
      (1)消除重复的接口
      (2)只提供所需的功能
      (3)适当的限制库的使用
     4.提供文档和注释
      (1)公共的文档应指定行为,而不是底层实现

七   设计通用的接口
     1.提供多种方法来完成同一功能
     2.提供定制能力

八   协调一般性和通用性
     1.提供多个接口
     2.优化常用功能

九   代码注释
     (1)前缀注释
        * 文件/类名
        * 最后一次修改时间
        * 原作者
        * 文件所实现特性的编号 (特性 ID)
        * 版权信息
        * 文件/类的简要描述
        * 未完成的特性
        * 已知的 bug

     (2)注释示例
        /*
         * Watermelon.cpp
         * 
         * $Id: Watermelon.cpp,v 1.6 2004/03/10 12:52:33 klep Exp $
         * 
         * Implements the basic functionality of a watermelon. All
         * unit are expressed in terms of seeds per cubic centimeter
         * Watermelon theory is based on the white paper "Alogorthms
         * for Watermelon Processing."
         *
         * The following code is (c)copyright 2004. FruitSoft, Inc.
         * All right reserved
         */

十   编写代码
     1.类定义在 C++ 中是一条语句,因此必须以分号结束。
     2.:: 指作用域解析操作符。
     3.在栈和堆上使用对象的区别
       (1)在栈上创建对象
          SpreadsheetCell myCell, anotherCell;

       (2)在堆上使用对象
          SpreadsheetCell *myCellp = new SpreadsheetCell();

       (3)如果用 new 来分配一个对象,用完该对象时要用 delete 来释放

     4.C++ 程序员通常把构造函数称为 "ctor"

     5.使用构造函数
       (1)在栈上使用构造函数
          SpreadsheetCell myCell(5);

       (2)在堆上使用构造函数
          SpreadsheetCell *myCell = new SpreadsheetCell(5);
          delete myCell;

       (3)不要尝试从类的一个构造函数调用另一个构造函数

     6.使用默认构造函数
       (1)在栈上使用构造函数
          SpreadsheetCell myCell;  //right
          SpreadsheetCell myCell();//wrong

       (2)在栈上创建对象时,要去掉默认构造函数的小括号
       (3)在堆上使用默认构造函数
          SpreadsheetCell *myCellp = new SpreadsheetCell();

       (4)什么时候需要使用构造函数
          SpreadsheetCell cells[3];//fails comilation without default ctor
         SpreadsheetCell *myCellp = new SpreadsheetCell[10];//alse fails

       (5)使用初始化列表
          1)初始化列表允许在创建数据成员的同时完成数据成员的初始化 
          2)使用初始化列表的情况

      数据成员                                         解释
      ------------------------------------------------------------------
      const 数据成员                              必须在创建时提供值
      引用数据成员                               引用无法独立存在
      没默认构造函数的对象成员       对象成员无法初始化
      没有默认构造函数的超类           见后面 
      ------------------------------------------------------------------

     7.对象的撤销
       (1)析构函数仅用于释放内存或释放其他资源是一个不错的想法

     8.浅复制与深复制
       (1)浅复制:只是从源对象直接将数据成员复制或赋值到目标对象
       (2)深复制:非浅复制
       (3)只要在类中动态分配了内存,就应该编写自己的复制构造函数来提供内存的深复制
       (4)在对一个对象进行赋值前,必须先释放此对象的所有动态分配的内存
       (5)只要类会动态分配内存,就需要编写析构函数、复制构造函数、赋值操作符
       (6)禁止对象赋值,可将复制构造函数与赋值操作符声明为私有成员
       (7)不必为私有复制构造函数和赋值操作符提供实现,编译器不要求

十一 精通类和对象
     1.不能在静态方法中访问非静态数据成员
     2.保证一个对象不会修改数据成员,可用 const 来标记

     3.保证一个方法不会修改数据成员,可用 const 来标记
       (1)在类定义中的声明 double getValue() const;
       (2)在源文件中的实现 
          double Spreadsheet::getValue() const
         {
            return this.mValue;
         }

     4.非 const 对象可以调用 const 和非 const 方法,const 对象只能调用const 方法

     5.应将所有不会修改对象的方法都声明为 const,并在程序中使用 const对象引用

     6.将变量置为 mutable,这样编译器允许在 const 方法中修改这个变量
     7.C++ 不允许仅基于方法的返回类型而重载一个方法名
     8.默认参数:从最右参数开始的连续参数表
     9.只能在方法声明中指定默认参数,在定义中并不指定
     10一个构造函数的所有参数都有默认值,此函数会作为默认构造函数
     11能利用默认参数做到的事情,利用方法重载也可以做,用你最熟悉的

     12内联:将方法体或函数体直接插入到代码调用处(相当于 #define 宏的安
       全版本),内联示例如下:

       (1)在类的源文件(SpreadsheetCell.cpp)
       inline double SpreadsheetCell::getValue() const
       {
           mNumAccess++;
           return mValue;
       }

       (2)或在类的声明文件中直接实现此方法而不用 inline 关键字
       //SpreadsheetCell.h
       double getValue() const (mNumAccesses++; return mValue;}

     13友元可以访问指定类中的 protected 和 private 数据成员和方法
       (1)声明友元类
          class SpreadsheetCell
          {
             public:
                 friend class Spreadsheet;
                //code omitted here
          };

       (2)声明友元方法
          class SpreadsheetCell
         {
             public:
                 friend bool checkSpreadsheetCell();
                 //code omitted here
         };


十二 C++ 中的继承机制
     1.超类指针(引用)在引用子类时,了类仍然会保留它们覆盖的方法。而在
       强制类型转换成超类对象时,子类会失去它们的独有特性。覆盖方法和子
       类数据的丢失称为切割。

     2.作为一条经验,要把所有的方法都用 virtual 声明 (包括析构函数,但
       是不包括构造函数) 来避免因遗漏关键字 virtual 而产生的相关问题。

     3.virtual 用法示例:
       class Sub : public Super
       {
           public:
           Sub();
           virtual void someMethod();
           virtual void someOtherMethod();
       }

     4.要把所有的析构函数都用 virtual 声明

     5.强制类型转换
       (1)静态转换 static_cast<type>
          示例:
          Sub* mySub = static_cast<Sub*>(inSuper);

       (2)动态转换 dynamic_cast<type>
          示例:
          Sub* mySub = dynamic_cast<Sub*>(inSuper);
          if (mySub == NULL)
         {
              //proceed to access sub methods on mySub
         }
   
   注意:如果对指针不能进行动态类型转换,指针则为 NULL, 而不是指
   向无意义的数据。

     6.进行向上强制类型转换时,要使用指向超类的指针或引用来避免切割问题。

     7.纯虚方法与抽象基类
       (1)纯虚方法: 在类定义中显示未定义的方法。
       (2)抽象类: 含有纯虚方法的类(不能实例化)。
       (3)纯虚方法语法定义: 在类定义中简单的设置方法等于 0,在 cpp 文件
          中不要编写其实现代码。
   示例:
   class SpreadsheetCell
   {
       public:
           SpreadsheetCell();
           virtual ~SpreadsheetCell();
           virtual void set(const std::string instring) = 0;
           virtual std::string getString() const = 0;
     };

     8.定制类型转换函数
       (1)double 类型转换成 string 类型
          #include <iostream>
          #include <sstream>
   
          double inValue;
          string myString;

          ostringstream ostr;
          ostr << inValue;
          myString = ostr.str();

       (2)string 类型转换成 double 类型
          #include <iostream>
          #include <sstream>
   
          double myDouble;
          string inString;
   
          istringStream istr(inString);
          istr >> myDouble;
         if (istr.fail())
        {
           myDouble = 0;
        }

     9.使用预编译指令避免重复包含头文件
       #ifndef _TEST_H_ 
       #define _TEST_H_ 
       // include header files here       
       // other code omitted here

       #endif
   
十三 覆盖方法的特殊情况
     1.在 C++ 中不能覆盖静态方法。
       (1)不能同时用 virtual 和 static 声明一个方法。
       (2)在对象上可以调用 static 方法,但 static 方法只存在于类中。

十四 利用模板编写通用代码
     1.模板相关概念
       (1)类模板: 存储对象的容器或数据结构。
       (2)模板的语法: 
          template <typename T>
         class Grid
         {
             public:
                 Grid(int inWidth, int inHeight);
                 Grid(const Grid<T>& src);
                 Grid<T>& operator=(const Grid<T>& rhs);
                 T& getElementAt(int x, int y);
                 const T& getElementAt(int x, int y);
                 void setElementAt(int x, int y, const T& inElem);

             protected:
                 void copyFrom(const Grid<T>& src);
                 T** mCells;
        };
        (3)语法解释
            template <typename T> : 指在类型 T 上定义的模板。
            Grid<T> : Grid 实际上是模板名。
            Grid<T> : 将作为类模板中的类名。

 (4)模板定义(实现)
    template <typename T>
    Grid<T>::Grid(int inWidth, int inHeight)
    {
        mCells = new T* [mWidth];
        for (int i = 0; i < mWidth; i++)
        {
            mCells[i] = new T[mHeight];
        }
    }

 (5)模板实例化
    Grid<int> myIntGrid;

十五 C++ 中的一些疑难问题
     1.引用 
       (1)定义: 另一个变量的别名, 对引用的修改会改变其所指向的变量。
       (2)引用变量必须在创建时就初始化。
          int  x = 3;   // right
          int& xRef = x;// right
          int& emptyRef;//wrong
          注: 类的引用数据成员可在构造函数的初始化列表中初始化。

       (3)不能创建指向未命名值的引用(const 常量值除外)
          int& unnameRef = 5;      //does not compile
          const int& unnameRef = 5;//works as expect

       (4)修改引用: 引用总是指向初始化时指定的那个变量。
          int x = 3, y = 4;
          int& xRef = x;
          xRef = y; // change x value to 4, doesn't make refer to y;
          xRef = &y; // doesn't compile, type not match
         注: 引用指向的变量在初始化之后不能再改变, 只能改变此变量的值

       (5)指针引用和引用指针
          //指针引用示例(指向指针的引用)
          int*  intP;
          int*& ptrRef = intP;
          ptrRef = new int;
         *ptrRef = 5;

         注:不能声明指向引用的引用, 也不能声明引用指针(指向引用的指针)
         int x = 3;
         int& xRef = x;
         int&& xDoubleRef = xRef; // not compile
         int&* refPtr = &xRef; // not compile
   
       (6)传引用vs传值
          1)效率。复制大对象和结构要花费很长时间。
          2)正确性。不是所有的对象都允许传值或正确的支持深复制。
          3)不想修改原对象,又利用以上两优点,可在参数前加 const。
         4)对简单内置类型(如int或double)要传值,其它所有情况可传引用。

       (7)引用vs指针
          1)引用让程序清晰,易于理解。
          2)引用比指针安全,不存在无效的引用,不需要明确解除引用。
          3)除非需要动态分配内存或在其它地方要改变或释放指针指向的值,否则都应使用引用而非指针。
     
     2.疑难字 const
       (1)const 变量
          使用 const 来声明变量,对不能对其修改,以保护变量。

       (2)const 指针
       //不能改变指针指向的值
          const int* ip;
          ip = new int[10];
          ip[4] = 5; // not compile
        或
          int const* ip;
          ip = new int[10];
          ip[4] = 5; // not compile
 
          //不能改变指针自身
          int* const ip;
          ip = new int[10]; // not compile
          ip[4] = 5;

         //既不能改变指针也不能改变指针指向的值
         const int* const ip = NULL;(无用的指针)
          注: const 可以放在类型前也可以放在类型后
   
       (3)const 应用规则
          const 应用于其左则的第一项。

       (4)把对象参数传递时,默认的做法是把传递 const 引用。

       (5)const 方法
          用 const 标识类方法,可以防止方法修改类中不可变的数据成员。

     3.关键字 static
       (1)关于连接: C++ 中的每个源文件是独立编译的,得到的对象连接在一
          起。

       (2)外部连接: 一个源文件中每个名字(如函数或全局变量)对其它源文件
          是可用的。

       (3)内部连接: 一个源文件中每个名字(如函数或全局变量)对其它源文件
          是不可用的。内部连接也叫静态连接。

       (4)函数和全局变量默认是外部连接。

       (5)声明前加 static 可指定为内部连接。

     4.关键字 extern 
       (1)作用: 与 static 相对,用来为位于它前面的名字声明外部连接。
       (2)extern 用法
          // AnotherFile.cpp
         extern int x; // 只是声明 x 为外部连接而不分配内存
         int x = 3;    //显示定义以分配内存
        或
          extern int x = 3;//声明和定义一起完成

          //FirstFile.cpp
         extern int x;
         cout << x << endl;

      5.强制类型转换
      (1)const_cast<type> 去除变量的常量性。
      示例:
      void g(char* str)
      {
          // body omitted here
      }
      void f(const char* str)
      {
          g(const_cast<char*>(str));
          // other code omitted here
      }      

 (2)static_cast<type> 显示的完成 C++ 语言支持的转换。
    示例:
    int x = 3;
    double result = static_cast<double>(i) /10;

    注: static_cast 进行类型转换时并不完成运行时类型检查。

 (3)dynamic_cast<type>
    1)对类型强制转换完成运行时类型检查。
    2)对指针转换失败时会返回 NULL。
    3)对引用转换失败时会抛出 bad_cast 异常。

 
6.函数指针
        (1)定义: 把函数地址作为参数,可以像变量一样使用。
        (2)定义函数指针: typedef bool(*YesNoFcn) (int, int);
        (3)用法示例

           //定义函数指针类型
           typedef string(*YesNoFcn)(int, int);

           void test(int value1, int values2, YesNoFcn isFunction)
          {
             cout << isFunction(value1, value2);
          }

         string intEqual(int intItem1, int intItem2)
         {
            return (intItem1 == intItem2) ? "match" : "not match";
         }

         //使用函数指针
          test(1, 1, &intEqual);

         注: & 是可选的


十六 C++ 中的 I/O 操作
     1.使用流
       (1)每个输入流都有一个相关联的源,每个输出流都有一个相关联的目的。

       (2)cout 和 cin 都是在 C++ 的 std 命名空间中预定义的流实例。

       (3)流的三种类型: 
          1)控制台输入输出流。
          2)文件流。
          3)字符串流。

       (4)输出流
          1)输出流在头文件 <ostream> 中定义,输入流在 <istream> 中定义<iosream> 中定义了输入输出流。

          2)cout 和 cin 指控制台输入输出流。

          3)<< 操作符是使用输出流的最简单的方法。

          4)流其它的输出方法
             1)put() 和 wirte()
             2)flush() 刷新输出
  
          5)处理输出错误
             1)cout.good()  流是否处于正常的可用状态。
             2)cout.bad()   流输出是否发生了错误。
             3)cout.fail()  如果最近的操作失败则返回 true
             4)cout.clear() 重置流的错误状态

   6)输出控制符
     1)endl         输出回车并刷新其缓冲区
     2)hex oct dec  以十六/八/十进制输出
     3)setw         设置输出数值数据时的字段占位符
     4)setfill    设置填充空位的占位符

       (5)输入流
          1)>> 输入流操作符
          2)输入方法
              1)get()    仅仅返回流中的下一个字符
              2)unget()    引起流回退一个位置
              3)peek()    预览下一个值
              4)getline()    从输入流中取一行数据

          3)处理输入错误
             1)good() 
             2)eof()

       (6)字符串流
          1)<ssteam>    定义了字符串流的头文件
         2)ostringstream  字符串输出流
         3)istringstream  字符串输入流

       (7)文件流
          1)<fstream>      定义了文件流的头文件
          2)ifstream    文件输入流
          3)ofstream    文件输出流
          4)seek()    定位流的位置
          5)tell()    查询流当前的位置

       (8)链接流
          1)定义: 在任何输入流与输出流之间建立连接,一旦访问就刷新输出。
          2)实现: 用输入流的 tie() 方法
          3)示例
            #include <iostream>
           #inlcude <fstream>
           #include <string>

           main()
           {            
                ifstream inFile("input.txt");
               ofstream outFile("output.txt");
     
                //set up a link between inFile and outFile.
                inFile.tie(&outFile);

               string nextToken;
               inFile >> nextToken;
         }


十七 C++ 中的异常
     1.抛出和捕获异常
       (1)<exception> 定义异常类的头文件。
       (2)抛出异常对象 throw exception()
       (3)向量的使用(整型)
        vector<int> myInts;
        for (int i = 0; i < 10; i++)
        {
             myInts.push_back(i);// 增加元素
             cout << myInts[i];
        }

       (4)string 风格的字符串转换成 C 风格的字符串
          string myString = "string style string";
          char* cStyleStrng = myString.c_str();

       (5)捕获运行时异常
          try
         {
            ...
          }
          catch (const runtime_error& e)
         {
           ...
         }

       (6)抛出和捕获无效参数异常
          throw invalid_argument("");

         try 
          {
            ...
          }
          catch (const invalid_argument& e)
          {
             ...
          }

         注: runtime_error 和 invalid_argument 定义在头文件<stdexcept> 中

       (7)匹配任何异常(...)
          try
          {
            // code omitted here
          }
          catch (...)
          {
            // code omitted
          }
         注: 不建议使用这种方式

       (8)使用抛出列表
          1)抛出列表: 一个函数或方法能抛出的异常列表
          2)必须为函数声明和实现都提供抛出列表
          3)没有抛出列表就可以抛出任何异常
         4)空的抛出列表不允许抛出任何异常

       (9)在覆盖方法中修改参数列表
          1)从列表中删除异常
          2)增加超类抛出列表中异常的子类
          3)不能完全删除抛出列表

       (10)显示异常消息
           可调用 exception 或子类的 what() 方法显示捕获到的异常消息
           示例:
           try
           {
               ...
           }
           catch (const exception& e)
           {
               cerr << e.what() << endl;
               exit(1);
           }
             
       (11)多态地捕获异常
           1)在多态地捕获异常时,要确保按引用捕获异常。如果按值捕获异常,就会遇到切割问题,丢失对象的信息。

           2)按引用捕获异常可以避免不必要的复制开销

       (12)如果异常处理不够仔细,就会导致内存和资源泄漏
           示例
           func ()
          {
            string str1;
            string* str2 = new string();
            throw exception();
            delete str2;     // 内存泄漏
          }

       (13)使用智能指针防止内存泄漏
           #include <memory> // 定义智能指针的头文件
           using namespace std;
           func ()
           { 
               string str1;

               // 智能指针,不用自己手动释放
              auto_ptr<string> str2(new string("hello"));
              throw exception();
           }

       (14)处理内存分配错误
           1)new 和 new [] 分配内存失败默认抛出 bad_alloc 异常
           2)可用 try/catch 捕获异常处理内存分配失败
           3)示例:
             try
             {
                 ptr = new int[numInts];
             }
             catch (bad_alloc& e)
            {
              cerr << "Unable to alloc memory!" << endl;
              return ;
            }
         或
          1)用 new(nothrow) 在内存分配失败时返回 NULL 来处理
          2)示例:
             ptr = new(nothrow) int[numInts];
            if (ptr == NULL)
            {
               cerr << "Unable to alloc memory!" << endl;
               return;
            }
         或
           1)用 set_new_handler() 回调函数定制分配失败时的行为
           2)示例
              void myNewHandler()
             {
                cerr << "Unable to allocate memory!" << endl;
                abort(); // 终止程序 <cstdlib>
             }
             
             #include <new>
            #include <cstdlib>
            #include <iostream>
            using namespace std;
      
            int main(int argc, char** argv)
           {
               new_handler oldHandler = set_new_handler(myNewHandler);

              // code omitted here

             set_new_handler(oldHandler);
             return (0);
         }

g2o&PCL 四阶多项式拟合 阅读详情

相关推荐

新能源知识库(68)复叠压缩式热泵蒸汽系统介绍

复叠压缩式热泵蒸汽系统通过多级压缩技术将低品位热能转化为高品位蒸汽,在汽车电镀场景中实现了高效、精准的能源利用。随着超高温工质与智能联供系统的发展,该技术将深度赋能电镀行业的高质量可持续发展。​:±1℃控温保障镀层均匀性,提升产品良率;多台复叠热泵+储热装置(如纺织厂6台热泵)复叠热泵+余热回收+智能控制(化工厂案例)​:无燃烧设计契合汽车行业ESG目标。单台高温热泵机组(如92P型号)复叠压缩式热泵蒸汽系统以。67.4万元(↓22%)600万–1200万元。事故率 ↓90%​​。150万–600万元。

竹君子之家 1420

好久没有用c++,转一个c++注意点

一 编程设计 1.将程序划分为多个子系统,包括子系统间的接口和依赖关系、子系统间的数据流、在各子系统间的来回输入输出、以及总的线程模型。 2.各个子系统的具体细节,包括进一步细分的类、类层次体系、数据结构、算法、特定的线程模型和错误处理。 二 设计流程 1.需求:功能需求和性能需求。 2.设计步骤 (1)把程序划分为通用...

weixin_33842304的博客 205

异常数据处理——3σ原则、箱线图

异常数据处理——3σ原则、箱线图 用不包括异常值的剩余数据的均值替换、删除DataFrame中某列有异常值的整行等方法

杨老师的小跟班(*∩_∩*) 9033

图形学 所有斜率均可用的中点画线法 C++实现

//经过多重优化的中点画线算法,输入为线段两端点的坐标值 //该算法经过数学推导,可以处理斜率不存在,斜率为零,斜率为负数,斜率绝对值大于一等各种情况 void Mid_point(const unsigned& x1, const unsigned& y1, const unsigned& x2, const unsigned& y2) { int dx = x2 - x1, dy = y2 - y1; enum Main_ChangeDirection { x, y

hanmo22357的博客 1893

STM32_USB复合设备开发实战:基于CubeMX插件简化HID与CDC集成

本文详细介绍了如何使用STM32CubeMX插件简化USB复合设备开发,特别是HID与CDC的集成。通过自动处理多设备描述符融合和端点资源分配,该插件显著降低了开发复杂度,帮助工程师快速实现键盘、鼠标和虚拟串口等复合功能,提升STM32 USB开发效率。

palm99的专栏 749

华为铁三角(AR、SR、FR)的考核指标设计

以和为核心,通过和实现协同。考核维度分为和,并随市场阶段动态调整权重。

从技术实践立足,从项目管理方法论延伸思考 2769

14 CPP函数的默认参数

因为第二个形参拥有了默认实参没有问题,但是在此之前,他后面的第三个形参必须也拥有默认实参才可以 ,只要调换以下位置,让它作为第一个函数声明,就错了.你看觉得上面说的很绕,其实就是,你可以给任何形参默认实参,但是,你需要在当前作用域提前给你已经声明了默认实参的形参后面的形参默认实参.原因:在函数声明中,所有在拥有默认实参的形参之后的形参必须拥有在这个或同一作用域中先前的声明中所提供的的默认实参.1 如果函数的声明和定义是分开书写的,在函数声明中书写默认参数,函数的定义中不能书写默认参数。

wade1010的专栏 877

用python画带有正负值的条形图

常见的条形图只能表现数据的大小,却不能表现值的正负关系。但是其实仅仅使用`pandas`和`matplotlib`两个包就可以实现y轴负轴的添加以及负值的显示,并且可以为正负值分别设置不同的颜色,让条形图看上去更加清晰,易于我们分析

weixin_44853840的博客 5384

C++的函数默认值

1.C语言中它的函数是不允许默认值的,每个设置的函数都必须有他的形参值。但是C++引入了默认值的说法。

Qianxueban的博客 459

PostgreSQL 核心原理:大字段(大对象)是如何被压缩和存储的(TOAST存储机制)

PostgreSQL通过TOAST机制高效处理大字段存储问题,解决单行超过8KB页大小限制的挑战。TOAST采用透明分片、按需加载和自动压缩策略,支持TEXT、JSONB等变长类型,无需用户干预。其核心包括四种存储策略(plain/external/main/extended),自动将大字段分片存入专用TOAST表,主表仅保留指针。读取时按需解压拼接,支持部分加载优化。TOAST表结构包含chunk_id、序列号和分片数据,配合内置PGLZ压缩算法,平衡存储效率与访问性能。该机制使PostgreSQL能稳定

数据知道的博客 2625

【HAL库】STM32CubeMX开发----STM32F407----ETH+LAN8720A+LWIP----ping通

本次实验以芯片为MCU,使用25MHz外部时钟源。以太网PHY层芯片为LAN8720A,由MCU引脚PA8提供时钟。

MQ0522的博客 4843

C++命名空间、缺省参数/默认参数、函数重载、静态库的使用与兼容问题解析

C++命名空间、缺省参数/默认参数、函数重载、静态库的使用与兼容问题解析!

烁岩的博客 786

一文搞懂数据标注

数据标注即通过分类、画框、标注、注释等,对图片、语音、文本等数据进行处理,标记对象的特征,以作为机器学习基础素材的过程。简言之,就是需要给数据做好标注,这样机器就能知道学习哪些内容。

女王の专属领地 9943

c++学习及注意点

fprintf 是一个非常强大的函数,可以用于将格式化数据输出到任意文件流。它在以下场景中非常有用:输出错误信息到标准错误(stderr),将日志或数据写入文件,需要灵活控制输出目标时。

qq_41496108的博客 518

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

cpp中一些需要注意的点

关于从文件种读取指定字节数的字符 void BagReader::read_string(string& str, int mem_size) { char* a = new char[mem_size]; this -> in_stream.read(a, mem_size); str = a; str = str.substr(0, mem_size); // cout << ++number << ", bag read .

qq_41617659的博客 355

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

C++SORT的cmp函数注意点

C++SORT的cmp函数注意点 static bool cmp(int a,int b){ //注意 //1.cmp函数是static类型 //2.返回值必须为bool //3.传参类型为传送迭代器的元素类型int return a+b>b+a; } int main(){ vector<int>ss(n); sort(ss.begin(),ss.end(),cmp); return 0; } ...

weixin_45459322的博客 404

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

使用C++的一些注意点

转载自【https://blog.youkuaiyun.com/devcloud/article/details/10786537】,内容:C++是一门被广泛使用的系统级编程语言,更是高性能后端标准开发语言;C++虽功能强大,灵活巧妙,但却属于易学难精的专家型语言,不仅新手难以驾驭,就是老司机也容易掉进各种陷阱......

yolan2626的博客 732

C++一些注意点

1.       数据类型定义时要注意,长整型或者其他加了long关键字的数据类型在说明的时候L要用大写,以免小写l和1不分。2.       变量命名习惯要统一,要么就用驼峰原则,首字母小写,其后的单词首字母大写,例如moneyIn,要么就用下滑线money_in,但不管怎么说,要保持一致,不要想到哪个就用哪个。3.       C++应当注意变量的初始化!!!尤其是用惯了C#,Java等语言之后和容易忽略这点,如果没有初始化的话,很容易出现各种问题。另外,初始化分为复制初始化和直接初始化两种方法,据说直

冷夜焰凝的专栏 685

c++ 注意点

记录《c++ primer》的书店例子在

IT小小鸟~~ 1094

关于C++的类的几点注意点

析构函数绝对不会有返回值,也没有任何参数,绝对不可能重载 析构函数用于释放在构造函数或对象生命周期内分配的资源,在对象结束生命后会自动调用析构函数来善后。感觉一般都是我们在构造对象的时候,在对象内部要手动申请一块内存,然后我们在析构函数中需要将其释放掉 即使是自己定义的类,C++也提供默认的成员逐一初始化。比如下面的代码 MyClass zhangsan; MyClass lisi=

GH_HOME的专栏 553

C++细节注意点

文章目录实现和声明的分离不使用 using namespace std;C++对C语言的增强重点1 引用引用的注意事项引用的本质指针引用常量型引用成员函数调用const修饰对象实例构造和析构函数实例拷贝构造函数拷贝构造函数的调用时机深拷贝浅拷贝深拷贝初始化列表类对象作为类成员的案例explicit 关键字new动态对象创建 完美代替malloc静态成员变量静态成员函数单例模式成员变量和成员属性分开...

weixin_39558227的博客 766

C++需要注意点

1、设定static成员变量初值时,不受任何存取权限的束缚。可以再还没有诞生任何对象的时候就处理static类型成员变量,但首先必须初始化它。 2、只要access level允许,任何函数都可以存取static成员变量。但如果你希望在产生任何object之前就存取其class的private static成员变量,则必须设计一个static成员函数。 3、四种不同的对象生存方式(in sta

XUZHENG19860228的专栏 568

C++指针详解(附难点易错点解析及注意事项)

本文系统地讲解了C/C++中指针的概念、使用及注意事项。首先,介绍了内存的分区(栈区、堆区、全局/静态存储区、常量存储区)及其特点。接着,详细解释了指针的定义、创建与释放、取址符和解引用符的使用,并通过代码示例展示了指针的操作和常见错误。文章还指出了指针的难点,如多级指针、数组与指针的关系、函数与指针的结合等,并列举了易错点,如野指针、悬垂指针、内存泄漏等。最后,提出了使用指针时的注意事项,如初始化指针、避免解引用空指针、使用智能指针等,以帮助读者更好地掌握指针的使用。

Xcq20230729的博客 1734

【笔记】C++指针需要注意的点

参考:C++ 指针的算术运算 指针是一个用数值表示的地址。因此,可以对指针执行算术运算。可以对指针进行四种算术运算:++、–、+、-。 假设 ptr 是一个指向地址 1000 的整型指针,是一个 32 位的整数,让我们对该指针执行下列的算术运算: ptr++ 在执行完上述的运算之后,ptr 将指向位置 1004,因为 ptr 每增加一次,它都将指向下一个整数位置,即当前位置往后移 4 个字节。这个...

sinat_37269729的博客 322

c++编程注意点之一

c++编程注意点之一 1.  尽量少用singleton,可以通过在main函数中传一个声明的对象; 2.   std流效率低,有加锁,多用fread, fwrite.

chenglinhust的专栏 832

c++类注意点

类的调用 1) 若A类想在类体内实例化对b,则B类需在A类定义之前有完整的定义。 class A { public: B b;//实例化对象b---->>>(错误)B类没有在A类之前没有定义 void fun_A() { b.fun_B(); } }; class B { public: void fun_...

qq_37451250的博客 235
上一篇: C++ 的 ::
下一篇: C语言程序的内存布局
i丹明扬
博客等级 码龄15年 331粉丝 115原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值