【C/C++】日常学习7

1. 输入\输出流操作
2. 构造函数参数参数列表初始化
3. C++中类的前向声明以及和#include的区别
4. 在函数后加const的意义

1. 输入\输出流操作

读取字符串的不同操作
cin:遇到空格、回车符就停止读取,空格、回车符是分隔符,不能读取空格或回车符
cin.get():遇到终止符号停止读取(默认为回车符),能够 读取空格,但流指针指向了终止字符。
cin.getline():遇到终止符停止读取(默认为回车符),能够读取空格,但流指针指向了终止字符后一个字符
cin.get (), cin.getline()不是必须读取一行数据 ,遇到终止字符就停止
getline()使用起来简单一些,但get()使得检查错误更简单。get()可以检查是因为读取整行而停止还是由于数组填满而停止。

#include <iostream>
using namespace std;

int main()
{
	cout<<"What year was your house built?\n";
	int year;
	cin>>year;		//读取数字 
	cin.get();		//读取空格并丢弃 
	cout<<"What is its street address?\n";
	char address[80];
	cin.getline(address,80);		//读取整行 
	cout<<"Year built:"<<year<<endl;
	cout<<"Address:"<<address<<endl;
	cout<<"Done!\n"; 
	
	return 0;
}

当cin读取年份时,将回车键生成的换行符留在了输入队列中,后面的cin.getline()看到换行符后,将认为是一个空行,并将一个空字符串付给address数组。解决办法:再读取地址之前先读取并丢弃换行符。
注意:cin和 cin.get()在读取结束后指针都会留在终止字符上,因此可能会对下一个输入造成影响。cin.getline()则指向终止字符后一个字符。但是cin流有一个默认状态是为输入操作符(即“>>"操作符)跳过空白,所以默认情况下用输入操作符读取时会跳过回车符等空白字符,实际上它是在缓冲区中的,可以通过noskipws操纵符让输入操作符不跳过空白字符,

cin>>noskipws>>a;
cin>>a;cin>>b;没有影响,>>过滤空白字符
cin>>a;cin.get(pt,20);有影响,cin.get(pt,20)无法过滤空白字符
cin>>a;cin.getline(pt,20);有影响,cin.getline(pt,20)无法过滤空白字符
cin.get(pt,20); cin>>b;没有影响,>>过滤空白字符
cin.get(pt,20); cin.get(ps,20);有影响,cin.get(ps,20)无法过滤空白字符
cin.get(pt,20); cin.getline(ps,20);有影响,cin.getline(ps,20)无法过滤空白字符
cin.getline(ps,20);cin>>b;没有影响,>>过滤空白字符
cin.getline(ps,20);cin.get(ps,20);没有影响,cin.getline(ps,20)不保留换行符
cin.getline(ps,20);cin.getline(ps,20);没有影响,cin.getline(ps,20)不保留换行符

标准输出流——分为成员函数控制输出格式和流操纵符控制输出格式两种方式
控制输出格式的成员函数
(1) cout.unsetf(ios::状态标志);——设置状态标志流成员函数
(2) cout.unsetf(ios::状态标志);——清除状态标志流成员函数unsetf
(3) cout.width(n);——设置域宽流成员函数
(4) cout.precision(n);——设置实数的精度流成员函数
(5) cout.fill(ch);——填充字符流成员函数

在这里插入图片描述

2. 构造函数参数参数列表初始化
构造函数的一项重要功能是对成员变量进行初始化,为了达到这个目的,可以在构造函数的函数体中对成员变量一一赋值,还可以采用参数初始化表。

#include <iostream>
using namespace std;
class Student{
private:
    char *m_name;
    int m_age;
    float m_score;
public:
    Student(char *name, int age, float score);
    void show();
};
//采用参数初始化表
Student::Student(char *name, int age, float score): m_name(name), m_age(age), m_score(score){
    //TODO:
}
void Student::show(){
    cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
}
int main(){
    Student stu("小明", 15, 92.5f);
    stu.show();
    Student *pstu = new Student("李华", 16, 96);
    pstu -> show();
    return 0;
}

运行结果:
小明的年龄是15,成绩是92.5
李华的年龄是16,成绩是96

注意:
(1) 使用参数初始化表并没有效率上的优势,仅仅是书写方便,尤其是成员变量较多时,这种写法非常简明明了。
(2) 参数初始化顺序与初始化表列出的变量的顺序无关,它只与成员变量在类中声明的顺序有关如以下代码
(3) 初始化 const 成员变量的唯一方法就是使用参数初始化表

#include <iostream>
using namespace std;
class Demo{
private:
    int m_a;
    int m_b;
public:
    Demo(int b);
    void show();
};
Demo::Demo(int b): m_b(b), m_a(m_b){ }
void Demo::show(){ cout<<m_a<<", "<<m_b<<endl; }
int main(){
    Demo obj(100);
    obj.show();
    return 0;
}

运行结果:
2130567168, 100

相当于

Demo::Demo(int b): m_b(b), m_a(m_b){
    m_a = m_b;
    m_b = b;
}
  1. C++中类的前向声明以及和#include的区别
    前向声明&include区别
    前向声明概念(forward declaration)

在程序中引入了类类型的B.在声明之后,定义之前,类B是一个不完全类型(incompete type),即已知B是一个类型,但不知道包含哪些成员.不完全类型只能以有限方式使用,不能定义该类型的对象,不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数.

前向声明应用场景

当你需要定义两个类或者结构,例如A和B,而这两个类需要互相引用,这时候在定义A的时候,B还没有定义,那怎么引用它呢,这时候就需要前向声明(forward declaration)了,前向声明格式如下: class B;当你在定义类A之前声明了B,那么就会在程序中引入了类类型的B,编译器知道你会在后面的某个地方定义类B,所以允许你在类A中引用类B。但是,在声明之后,定义之前,类B是一个不完全类型(incompete type),即已知B是一个类型,但不知道这个类型的一些性质(比如包含哪些成员和操作)。

前向声明的使用限制:(就拿上面声明B类说明)

1.不能够定义B类的对象;

2.可以用于定义只想这个类型的指针或者引用;

3.用于声明使用该类型作为形参或者返回类型的函数;

除了上面的限制,我们可以用它做些什么事情吗?
在C++中,如果要编写一个新类的头文件,一般是要#include一堆依赖的头文件,但利用前向声明和c++编译器的特性,可以减少这里的工作量。
因为c++编译器做的事情主要是:1.扫描符号;2.确定对象大小。利用这个特性,当我们编写一个新类的头文件时,就可以用前向声明,减少大量的#include,减少编译的工作量。

例如:

1.B类用到A类,操作如下,就不需要加A.h了,减少编译工作量

 //B.h
class A;//调用类A,前向声明
 class B
{
 private:
 	A *a; //声明指针
 };

2.在声明成员函数的形参或者返回类型时,也可以用前向声明。即使我们没有定义一个foo类,也可以用,因为成员函数不占类对象的大小,编译器可以确定对象大小,前向声明的作用在于告诉编译器这个一个在别的地方定义的类型。这样编译器就能生成正确的符号表了。

 //Sample.h
class foo;
class Sample
 {
 private:
 foo foo_test(foo &);
};

4. 在函数后加const的意义

我们定义的类的成员函数中,常常有一些成员函数不改变类的数据成员,也就是说,这些函数是"只读"函数,而有一些函数要修改类数据成员的值。如果把不改变数据成员的函数都加上const关键字进行标识,显然,可提高程序的可读性。其实,它还能提高程序的可靠性,已定义成const的成员函数,一旦企图修改数据成员的值,则编译器按错误处理。 const成员函数和const对象 实际上,const成员函数还有另外一项作用,即常量对象相关。对于内置的数据类型,我们可以定义它们的常量,用户自定义的类也一样,可以定义它们的常量对象。

c++ 函数前面和后面 使用const 的作用:

(1) 前面使用const 表示返回值为const——const int getValue();
(2) 后面加 const表示函数不可以修改class的成员——int getValue2() const;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值