c++入门学习草稿【持续更新中..】

 

指针运算符成员运算符 . 指向成员的运算符 -> 下标运算符[]

 

C++混合运算类型转换规则

 

字符可以作为整数参与数值运算,整数值为其在ASCII码表对应的数值。

操作数为字符或短整型时,系统自动转换成整型。

操作数为实型时,系统自动转换成双精度型。

当两数操作数类型不同时,将精度低的操作数的数据类型变换到与另一操作数类型相同再进行运算。

 

案例:输出整数,浮点数,字符9+1.5-'a'混合运算的值。

#include<iostream>
using namespace std;
int main()       //主函数
{
  cout<<9+1.5-'a'<<endl;
  return 0;
}

执行本程序之后,则会输出-86.5。

类型转换是由系统自动进行的.




 

 

将有符号数据赋值给无符号变量,并输出。

#include<iostream>
using namespace std;
int main()       //主函数
{
  unsigned short num_1; //定义无符号变量
  short int num_2=-10; //定义有符号的短整型变量且赋值
  num_1=num_2; //赋值
  cout<<num_1<<' '<<num_2<<endl; //输出
  return 0;
}

执行本程序之后,则会输出65526 -10。

会先获取-10的补码,16个二进制位,将它传给num_1,num_1是无符号型变量,补码的16个二进制位的十进制是65526。



 

 

 

 

 

C++提供了一种特殊的运算符,逗号运算符,可以将两个表达式连接起来。

逗号运算符又称为顺序求值运算符,一般形式为

表达式1,表达式2

逗号表达式求解过程是:先求解表达式1的值,再求解表达式2的值,但是整个表达式的值是表达式2的值。

案例:使用逗号表达式输出变量的值。

#include<iostream>
using namespace std;
int main()       //主函数
{
  int num_1; //定义整型变量
  num_1=3*5,4*5; //不加括号的逗号表达式
  cout<<num_1<<endl;
  num_1=(3*5,4*5); //加括号的逗号表达式
  cout<<num_1<<endl;
  return 0;
}

执行本程序之后,则会输出

15

20

为什么上面加括号和不加括号输出的值不一样呢?

不加括号时:赋值运算符的优先级高于逗号运算符,因此会先求解a=3*5,程序是自左向右运行的,后面的4*5也会运行,但是没有存储4*5的结果。

加括号时:由于()的优先级大于=,所以会先执行()里面的程序,3*5也会执行但是没有存储结果,到最后的4*5才会存储结果。


清除缓存区

C清除缓存区
在C语言中,有以下几种方法:

使用fflush(stdin);语句:
优点:简单便捷,直接把这条语句放在输入语句之前就可以了。
缺点:在C语言的标准中没有明确规定这种用法,有些编译器不支持这种用法,但是编译器并
不会报错,只不过缓冲区的内容依然存在。

使用getchar()语句:
它的作用是单个的读取缓冲区里的数据,直接获取空白符,将缓冲区的“错误信息”过滤掉,这是最常使用的方法。
具体的它还可以有两种用法:
2.1. 直接在输入语句前插入语句getchar();
2.2. 使用while( ( getchar() ) != ’ \n’);读取缓冲区字符直到结束并丢弃他们。

C++清除缓存区
使用cin.ignore(numeric_limits :: max() , ‘\n’)语句:
这条语句要在cin语句之后使用,表示放弃包含换行符的输入流中的所有内容。
使用 cin.sync() 语句:
同样的,这条语句也是要在cin语句之后使用,表示放弃缓冲区中的所有内容。
使用cin>>ws;语句:
这也是在cin语句之后使用,它告诉编译器忽略缓冲区,并且在字符串或字符数组的实际内容之前丢弃所有的空格。

 

循环

 

 

 1 #include<iostream>
 2 
 3 using namespace std;
 4 int main()
 5 {
 6     int my_array[] = { 1,2,3,4,5,6,7,8 };
 7     // 不会改变 my_array 数组中元素的值
 8     // x 将使用 my_array 数组的副本
 9     for (int x : my_array)
10     {
11         x *= 2;
12         cout << x <<endl;
13     }
14     for (int i : my_array)//查阅数组中的值
15     {
16         cout << i<< endl;
17     }
18     
19     // 会改变 my_array 数组中元素的值
20     // 符号 & 表示 x 是一个引用变量,将使用 my_array 数组的原始数据
21     // 引用是已定义的变量的别名
22     for (int& x : my_array)
23     {
24         x *= 2;
25         cout << x << endl;
26     }
27     for (int i : my_array)
28     {
29         cout << i <<endl;
30     }
31     // 还可直接使用初始化列表
32     for (int x : { 1, 2, 3, 4, 5 })
33     {
34         x *= 2;
35         cout << x << endl;
36     }
37 }

 

 很明显,&操作的是原数组中的值.

 

C++通过对象的引用变量来访问对象中的成员

在C++中,如果为一个对象定义了一个引用变量,它们是共占同一段存储单元的,实际上它们是同一个对象,只是用不同的名字表示而已,因此完全可以通过引用变量来访问对象中的成员。

//time2与time1共占同一段存储单元,因此time2.hour就是time1.hour。
class Time
{
  public: //声明以下是公用的
    int day;
    int hour;
    int minute; 
};
Time time1;//定义对象time1
Time &time2=time1;//定义Time类引用变量time2,并初始化为time1 
cout<<time2.hour; //输出time1中的成员hour

 

 

在栈上创建对象可以写作Student stu()Student stu,在堆上创建对象可以写作Student *pstu = new Student()Student *pstu = new Student,它们都会调用构造函数 Student()。

 

继承中的特点

 

 

  • 1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public, protected, private

  • 2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected, protected, private

  • 3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private, private, private

 

但无论哪种继承方式,上面两点都没有改变:

 

  • 1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;

  • 2.protected 成员可以被派生类访问。

 

 

使用初始化列表来初始化字段:

 

Line::Line( double len): length(len) {
  cout << "Object is being created, length = " << len << endl;
}

 

上面的语法等同于如下语法:

 

Line::Line( double len) {
  length = len; cout << "Object is being created, length = " << len << endl;
}
 

假设有一个类 C,具有多个字段 X、Y、Z 等需要进行初始化,同理地,您可以使用上面的语法,只需要在不同的字段使用逗号进行分隔,如下所示:

C::C( double a, double b, double c): X(a), Y(b), Z(c)
{
  .......
}
 
 
 
 
 
 
构造函数的调用是强制性的,一旦在类中定义了构造函数,那么创建对象时就一定要调用,不调用是错误的。如果有多个重载的构造函数,那么创建对象时提供的实参必须和其中的一个构造函数匹配;反过来说,创建对象时只有一个构造函数会被调用。

 

构造函数初始化列表还有一个很重要的作用,那就是初始化 const 成员变量。初始化 const 成员变量的唯一方法就是使用初始化列表。例如 VS/VC 不支持变长数组(数组长度不能是变量),我们自己定义了一个 VLA 类,用于模拟变长数组,请看下面的代码:
class VLA{
private:
    const int m_len;
    int *m_arr;
public:
    VLA(int len);
};

//必须使用初始化列表来初始化 m_len
VLA::VLA(int len): m_len(len){
    m_arr = new int[len];
}

  


VLA 类包含了两个成员变量,m_len 和 m_arr 指针,需要注意的是 m_len 加了 const 修饰,只能使用初始化列表的方式赋值,如果写作下面的形式是错误的:

 

class VLA{
private:
    const int m_len;
    int *m_arr;
public:
    VLA(int len);
};

VLA::VLA(int len){
    m_len = len;
    m_arr = new int[len];
}

  

 

拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:

  • 通过使用另一个同类型的对象来初始化新创建的对象。

  • 复制对象把它作为参数传递给函数。

  • 复制对象,并从函数返回这个对象。

如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。

 

析构函数(Destructor)也是一种特殊的成员函数,没有返回值,不需要程序员显式调用(程序员也没法显式调用),而是在销毁对象时自动执行。

注意:

析构函数没有参数,不能被重载,因此一个类只能有一个析构函数。如果用户没有定义,编译器会自动生成一个默认的析构函数。

创建对象时系统会自动调用构造函数进行初始化工作,同样,销毁对象时系统也会自动调用一个函数来进行清理工作,例如释放分配的内存、关闭打开的文件等,这个函数就是析构函数。

posted @ 2021-02-03 12:04  泥烟  阅读(58)  评论(0编辑  收藏  举报