c++大学教程以及相关内容笔记整理

《C++大学教程》一本很详细的c++书籍,详细到基本可以当笔记来用  当然作为一个小白初学者还是整理一下笔记,顺便回顾。其中有一部分转载网上相关比较详细的内容

1 从C迁移到C++

c是c++的扩展以及增强;

不要假定没有数据类型就是int型,要显式的写出来(如:int main() );

初始化优于赋值(PITA规则);

在for循环中,计数变量可以在循环内声明(for(int i=0;i<5;++i));

在C++中,全局变量可以用表达式或者函数的调用来初始化,而不仅仅是使用常数;

不需要在编译时就知道数组的初始化值:(下面例子,变量a及b在堆栈中,编译时他们的值是未知的)

                  

void someFunction(void)
{
     int a=1,b=2;
     int someArray [] ={a,b};  //Error in C ,OK in C++
}
c++中的布尔类型,你可以这样写:

bool isGreater(int x,y)
{
    return x>y;
}
c++中不再允许Void *型指针进行隐式转换;

const说明某个对象是常量,并且所有常量必须初始化;

类型强制转换:

 static_cast关键字用来执行在不同的表示中要求”等价“的转换 (static_cast<new_type>(expression)

const_cast显式的添加或取消对象的常量属性


2.命名空间

关键字 namespace

域解析运算符  :: 

//using声明
namespace A
{
    int x=1;
    ...
}
void someFunction()
{
    using A::x;
    int a=x;
    using A::  ...
    ...
}

   //using 指令
namespace A
{
    int x=1;
    ...
}
void someFunction()
{
    using namespace A;
    x=0;      //use A::x
   ...
}

using指令使用后,可以一劳永逸,对整个命名空间的所有成员都有效,非常方便。而using声明,则必须对命名空间的不同成员名称,一个一个地去声明,非常麻烦。

一般情况下,对偶尔使用的命名空间成员,应该使用命名空间的作用域解析运算符来直接给名称定位。而对一个大命名空间中的经常要使用的少数几个成员,提倡使用using声明,而不应该使用using编译指令。只有需要反复使用同一个命名空间的许多数成员时,使用using编译指令,才被认为是可取的。


3.输入输出基础

#include<iostream>
using std::cout;
int main()
{
    cout<<4<<"ok"<<endl;
    int i;
    double d;
    std::cin>>i>>d;
}

4.引用变量

引用变量即创建变量和对象的别名


#include<iostream>
void addOne(int &arg)
{
    ++arg;
}
int main()
{
    int someVariable=0;
    addOne(someVariable);
    std::cout<<someVariable<<endl;
}

/*  output:

1

*/

创建引用变量:

int data =0;
int &refData=data
所有引用都必须初始化,当需要支持常量对象或临时对象时,一定要使用const限定引用,但是不要用const限定引用名称本身。


5.动态内存分配

关键字new后面跟随一个类型,从而在空闲存储区中分配这种类型的单个对象的空间,关键字delete来释放由new分配的空间。

int *ptrInt1=new int;   //value is unknown
int *ptrInt2=new int();  //value is zero
double *ptrDouble=new double(3.1415);   //初始化基本类型
delete ptrInt1;  //释放
int *ptrInt=new int[5];    //为对象的数组创建空闲空间,在空闲空间中基本类型的数组不能被初始化
delete [] ptrInt;     //释放,一定用空[].

6.类

编写类定义:

class Circle
{
   //all data and member functions inside the Circle
};
C++的关键数据隐藏原则确保类的用户不能直接操作数据成员
访问限定符:

private:私有类成员只能被类的成员函数访问

public:共有类成员允许不受限制的被访问,作为类的公共接口

protected:对类的成员函数以及这个类的派生类的成员函数访问

class Circle
{
    public:
  //all public members
    private:
  //all private members
};
模块化举例:

//  File circle.h
#ifndef CIRCLE_H_INCLUDED
#define CIRCLE_H_INCLUDED

class Circle
{
public:
   
    void storeRadius(int newRadius);
    int getRadius() const;
    double getArea() const;
private:
    int radius;
};

#endif // CIRCLE_H_INCLUDED

//  File circle.cpp
#include "circle.h"
void Circle::storeRadius(int newRadius)
{
    if(newRadius>0)
        radius=newRadius;
}
int Circle::getRadius() const
{
    return radius;
}
double Circle::getArea() const
{
    double const pi=3.1415;
    return pi*radius*radius;

}


//   File main.cpp
#include <iostream>
#include "circle.h"
using namespace std;

int main()
{
    Circle real;
    real.storeRadius(6);
    cout<<"This radius is "<<real.getRadius()<<endl<<"The area "<<real.getArea()<<endl;
    Circle *ptr=new Circle;
    ptr->storeRadius(3);
    cout<<"this radius is "<<ptr->getRadius()<<endl<<"the area "<<ptr->getArea()<<endl;
    
}

内联函数:

  内联函数是其代码代替了通常生成的汇编语言“调用”的函数

  隐式内联函数是完全在类内部定义的函数

  显式内联函数出现在类定义之外,但是仍在类的头文件中。关键字inline必须在函数声明、定义、或者声明以及定义中出现

  当常量成员函数需要修改非静态数据成员时,使用关键字mutable

  枚举(enum):私有枚举,公有枚举



7.构造函数和析构函数

转载自:https://www.cnblogs.com/mr-wid/archive/2013/02/19/2917911.html
        构造函数主要用来在创建对象时完成对对象属性的一些初始化等操作, 当创建对象时, 对象会自动调用它的构造函数。一般来说, 构造函数有以下三个方面的作用:
            ■ 给创建的对象建立一个标识符;
            ■ 为对象数据成员开辟内存空间;
            ■ 完成对象数据成员的初始化。
        
 
        当用户没有显式的去定义构造函数时, 编译器会为类生成一个默认的构造函数, 称为 "默认构造函数", 默认构造函数不能完成对象数据成员的初始化, 只能给对象创建一标识符, 并为对象中的数据成员开辟一定的内存空间。
        
   
        无论是用户自定义的构造函数还是默认构造函数都主要有以下特点:
            ①. 在对象被创建时自动执行;
            ②. 构造函数的函数名与类名相同;
            ③. 没有返回值类型、也没有返回值;
            ④. 构造函数不能被显式调用。

构造函数的显式定义
    由于在大多数情况下我们希望在对象创建时就完成一些对成员属性的初始化等工作, 而默认构造函数无法满足我们的要求, 所以我们需要显式定义一个构造函数来覆盖掉默认构造函数以便来完成必要的初始化工作, 当用户自定义构造函数后编译器就不会再为对象生成默认构造函数。
    
    在构造函数的特点中我们看到, 构造函数的名称必须与类名相同, 并且没有返回值类型和返回值, 看一个构造函数的定义:

复制代码
 1     #include <iostream>
 2 
 3     using namespace std;
 4 
 5     class Point
 6     {
 7         public:
 8             Point()     //声明并定义构造函数
 9             {
10                 cout<<"自定义的构造函数被调用...\n";
11                 xPos = 100;         //利用构造函数对数据成员 xPos, yPos进行初始化
12                 yPos = 100;
13             }
14             void printPoint()
15             {
16                 cout<<"xPos = " << xPos <<endl;
17                 cout<<"yPos = " << yPos <<endl;
18             }
19 
20         private:
21             int xPos;
22             int yPos;
23     };
24 
25     int main()
26     {
27         Point M;    //创建对象M
28         M.printPoint();
29 
30         return 0;
31     }
复制代码

 
    编译运行的结果:

复制代码
        自定义的构造函数被调用...
        xPos = 100
        yPos = 100

        Process returned 0 (0x0)   execution time : 0.453 s
        Press any key to continue.
复制代码

 


    代码说明:
        在Point类的 public 成员中我们定义了一个构造函数Point() , 可以看到这个Point构造函数并不像 printPoint 函数有个void类型的返回值, 这正是构造函数的一特点。在构造函数中, 我们输出了一句提示信息, "自定义的构造函数被调用...", 并且将对象中的数据成员xPos和yPos初始化为100。
        
        在 main 函数中, 使用 Point 类创建了一个对象 M, 并调用M对象的方法 printPoint 输出M的属性信息, 根据输出结果看到, 自定义的构造函数被调用了, 所以 xPos和yPos 的值此时都是100, 而不是一个随机值。
        
        需要提示一下的是, 构造函数的定义也可放在类外进行。
        
        
        


        
三、有参数的构造函数
    在上个示例中实在构造函数的函数体内直接对数据成员进行赋值以达到初始化的目的, 但是有时候在创建时每个对象的属性有可能是不同的, 这种直接赋值的方式显然不合适。不过构造函数是支持向函数中传入参数的, 所以可以使用带参数的构造函数来解决该问题。
    

复制代码
 1     #include <iostream>
 2 
 3     using namespace std;
 4 
 5     class Point
 6     {
 7         public:
 8             Point(int x = 0, int y = 0)     //带有默认参数的构造函数
 9             {
10                 cout<<"自定义的构造函数被调用...\n";
11                 xPos = x;         //利用传入的参数值对成员属性进行初始化
12                 yPos = y;
13             }
14             void printPoint()
15             {
16                 cout<<"xPos = " << xPos <<endl;
17                 cout<<"yPos = " << yPos <<endl;
18             }
19 
20         private:
21             int xPos;
22             int yPos;
23     };
24 
25     int main()
26     {
27         Point M(10, 20);    //创建对象M并初始化xPos,yPos为10和20
28         M.printPoint();
29 
30         Point N(200);       //创建对象N并初始化xPos为200, yPos使用参数y的默认值0
31         N.printPoint();
32 
33         Point P;            //创建对象P使用构造函数的默认参数
34         P.printPoint();
35 
36         return 0;
37     }
复制代码

 
    编译运行的结果:

复制代码
        自定义的构造函数被调用...
        xPos = 10
        yPos = 20
        自定义的构造函数被调用...
        xPos = 200
        yPos = 0
        自定义的构造函数被调用...
        xPos = 0
        yPos = 0

        Process returned 0 (0x0)   execution time : 0.297 s
        Press any key to continue.
复制代码

 


    代码说明:
        在这个示例中的构造函数Point(int x = 0, int y = 0) 使用了参数列表并且对参数进行了默认参数设置为0。在 main 函数中共创建了三个对象 M, N, P。
            M对象不使用默认参数将M的坐标属性初始化10和20;
            N对象使用一个默认参数y, xPos属性初始化为200;
            P对象完全使用默认参数将xPos和yPos初始化为0。

            
            


            
三、构造函数的重载
    构造函数也毕竟是函数, 与普通函数相同, 构造函数也支持重载, 需要注意的是, 在进行构造函数的重载时要注意重载和参数默认的关系要处理好, 避免产生代码的二义性导致编译出错, 例如以下具有二义性的重载:
    

复制代码
        Point(int x = 0, int y = 0)     //默认参数的构造函数
        {
            xPos = x;
            yPos = y;
        }

        Point()         //重载一个无参构造函数
        {
            xPos = 0;
            yPos = 0;
        }
复制代码

       
    在上面的重载中, 当尝试用 Point 类重载一个无参数传入的对象 M 时, Point M; 这时编译器就报一条error: call of overloaded 'Point()' is ambiguous 的错误信息来告诉我们说 Point 函数具有二义性, 这是因为Point(int x = 0, int y = 0) 全部使用了默认参数, 即使我们不传入参数也不会出现错误, 但是在重载时又重载了一个不需要传入参数了构造函数Point(), 这样就造成了当创建对象都不传入参数时编译器就不知道到底该使用哪个构造函数了, 就造成了二义性。
    
    
    

 


四、初始化表达式
    对象中的一些数据成员除了在构造函数体中进行初始化外还可以通过调用初始化表来进行完成, 要使用初始化表来对数据成员进行初始化时使用: 号进行调出, 示例如下:
    

        Point(int x = 0, int y = 0):xPos(x), yPos(y)  //使用初始化表
        {
            cout<<"调用初始化表对数据成员进行初始化!\n";
        }

       
    在 Point 构造函数头的后面, 通过单个冒号: 引出的就是初始化表, 初始化的内容为 Point 类中int型的 xPos 成员和 yPos成员, 其效果和 xPos = x; yPos = y; 是相同的。
    
    与在构造函数体内进行初始化不同的是, 使用初始化表进行初始化是在构造函数被调用以前就完成的。每个成员在初始化表中只能出现一次, 并且初始化的顺序不是取决于数据成员在初始化表中出现的顺序, 而是取决于在类中声明的顺序。
    
    此外, 一些通过构造函数无法进行初始化的数据类型可以使用初始化表进行初始化, 如: 常量成员和引用成员, 这部分内容将在后面进行详细说明。使用初始化表对对象成员进行初始化的完整示例:
    

View Code

 



    


    
五、析构函数
    与构造函数相反, 析构函数是在对象被撤销时被自动调用, 用于对成员撤销时的一些清理工作, 例如在前面提到的手动释放使用 new 或 malloc 进行申请的内存空间。析构函数具有以下特点:
        ■ 析构函数函数名与类名相同, 紧贴在名称前面用波浪号 ~ 与构造函数进行区分, 例如:~Point();
        ■ 构造函数没有返回类型, 也不能指定参数, 因此析构函数只能有一个, 不能被重载;
        ■ 当对象被撤销时析构函数被自动调用, 与构造函数不同的是, 析构函数可以被显式的调用, 以释放对象中动态申请的内存。

 


    当用户没有显式定义析构函数时, 编译器同样会为对象生成一个默认的析构函数, 但默认生成的析构函数只能释放类的普通数据成员所占用的空间, 无法释放通过 new 或 malloc 进行申请的空间, 因此有时我们需要自己显式的定义析构函数对这些申请的空间进行释放, 避免造成内存泄露。

复制代码
 1 #include <iostream>
 2      #include <cstring>
 3 
 4      using namespace std;
 5 
 6      class Book
 7      {
 8          public:
 9              Book( const char *name )      //构造函数
10              {
11                  bookName = new char[strlen(name)+1];
12                  strcpy(bookName, name);
13              }
14              ~Book()                 //析构函数
15              {
16                  cout<<"析构函数被调用...\n";
17                  delete []bookName;  //释放通过new申请的空间
18              }
19              void showName() { cout<<"Book name: "<< bookName <<endl; }
20 
21          private:
22              char *bookName;
23      };
24 
25      int main()
26      {
  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++大学教程(目录) 第1章 计算机与C++编程简介-------------------------------------------------1 1.1 简介--------------------------------------------------------------1 1.2 什么是计算机------------------------------------------------------3 1.3 计算机组成--------------------------------------------------------3 1.4 操作系统的变革----------------------------------------------------4 1.5 个人计算、分布式计算与客户/服务器计算-----------------------------4 1.6 机器语言、汇编语言和高级语言--------------------------------------5 1.7 C语言与C++的历史--------------------------------------------------6 1.8 C++标准库---------------------------------------------------------7 1.9 Java、Internet与万维网--------------------------------------------7 1.10 其它高级语言------------------------------------------------------8 1.11 结构化编程--------------------------------------------------------8 1.12 典型C++环境基础---------------------------------------------------8 1.13 C++与本书的一般说明----------------------------------------------10 1.14 C++编程简介------------------------------------------------------11 1.15 简单程序:打印一行文本-------------------------------------------12 1.16 简单程序:两个整数相加-------------------------------------------15 1.17 内存的概念-------------------------------------------------------18 1.18 算术运算---------------------------------------------------------19 1.19 判断:相等与关系运算---------------------------------------------21 1.20 新型头文件与名字空间---------------------------------------------24 1.21 有关对象的思考---------------------------------------------------25 小结------------------------------------------------------------------27 术语------------------------------------------------------------------29 自测练习--------------------------------------------------------------31 自测练习答案----------------------------------------------------------33 练习------------------------------------------------------------------34 第2章 控制结构-----------------------------------------------------------38 2.1 简

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值